본문 바로가기
Work/Java

[Java] String, StringBuffer, StringBuilder 차이점

1. String

int, long, double, float, boolean, char와 같은 Primitive타입이 아닌

reference 타입의 참조형 변수입니다.

가장 많이 사용되는 자료형중 하나이며,

한번할당된 공간이 변하지 않는 immutable 자료형입니다.

그러므로 초기공간과 다른 값에 대한 연산은 많은 시간과 자원을 사용하게 된다.

특히 + 연산의 경우가 그러하다. 기존의 래퍼런스 공간은 사라지고 추가연산시마다 변수생성과 초기화를 반복하며,

가비지가 급격하게 많이 늘어나게 되므로 StringBuilderStringBuffer를 사용하는게 유리합니다.

 

 

3. StringBuilder와 StringBuffer

위 둘은 모두 가변적이지고 가변적인 데이터 연산시 String보다 훨씬 빠르다.

 

public class StringBufferPerformanceTest{
    public static void main(String[] args){
        // (1) String의 +연산을 이용해서 10,000개의 *를 이어붙입니다.
        //시작시간을 기록합니다.(millisecond단위)
        long startTime1 = System.currentTimeMillis();
        String str="";
        for(int i=0;i<10000;i++){
            str=str+"*";
        }
        //종료시간을 기록합니다.(millisecond단위)
        long endTime1 = System.currentTimeMillis();
        
        // (2) StringBuffer를 이용해서 10,000개의 *를 이어붙입니다.
        //시작시간을 기록합니다.(millisecond단위)                
        long startTime2 = System.currentTimeMillis();
        StringBuffer sb = new StringBuffer();
        for(int i=0;i<10000;i++){
            sb.append("*");
        }
        //종료시간을 기록합니다.(millisecond단위)
        long endTime2 = System.currentTimeMillis();
        
        // 방법(1)과 방법(2)가 걸린 시간을 비교합니다.
        long duration1 = endTime1-startTime1;
        long duration2 = endTime2-startTime2;
        
        System.out.println("String의 +연산을 이용한 경우 : "+ duration1);
        System.out.println("StringBuffer의 append()을 이용한 경우 : "+ duration2);
    }
}
출력 〉 String의 +연산을 이용한 경우 : 30
         StringBuffer의 append()을 이용한 경우 : 1

 

10만번 이상의 연산시, 비용의 어마어마한 차이를 확인할 수 있다.

 

그렇다면, StringBuffer 와 StringBuilder의 차이는 무엇일까?

위 둘의 차이는 동기화에 있다.

StringBuffer는 동기화를 보장하지만, StringBuilder의 경우 동기화를 보장하지 않는다.

따라서 멀티 스레드 환경에서 사용하는 경우 StringBuffer (Thread-Safe) 를 사용한다.

 

 

+ P.S

 

 

String 리터럴 선언과 String객체의 차이

String str1= "madplay";
String str2= "madplay";

String str3 = new String("madplay");
String str4 = new String("madplay");

 

변수가 선언될떄 Heap영역안에서도 String의 경우,  

immutable 자료형이기 때문에 상수영역에 선언되어 맵핑되는것을 확인 할 수 있다.

반대로 객체로 생성되는 경우, 각각의 인스턴스가 힙 내 공간을 차지하므로, 다른 주소를 참조하게된다.

이는 문자열을 비교하는 경우 확인해볼수 있다.

 

	public static void main(String[] args) {
		String str1= "Bang";
		String str2= "Bang";

		String str3 = new String("Bang");
		String str4 = new String("Bang");

		System.out.println(str1==str2);
		System.out.println(str1.equals(str2));
		System.out.println(str3==str4);
		System.out.println(str3.equals(str4));
		
	}

equals 메소드를 통해, String 변수값을 비교하는 경우, 올바른 비교가 가능하지만,

변수자체를 == 연산을 통해 비교하는 경우, 저장되있는 주소지를 비교하게 되므로, 

상수영역에 선언된 리터털변수는 동일한 위치를 가지고,

객체롤 생성된 녀석들은 각각 다른 영역을 차지했음을 확인할수 있다.

 

 

 

 

https://madplay.github.io/post/java-string-literal-vs-string-object