ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [JAVA] String/String Builder/String Buffer 비교
    Language/Java 2019. 10. 20. 16:34

     

     

    자바에서 문자열을 이용할 때 주로 사용하는 대표적인 클래스가 바로 String클래스입니다.

     

    하지만 String 클래스는 immutable속성이 있어서 문자열을 빈번하게 수정하는 경우 성능 저하가 일어날 수 있습니다.

    따라서, 문자열을 사용하는 경우 String클래스 대신 String Builder, String Buffer를 사용하라는 이야기를 들어보셨을 텐데요. 그렇다면 왜 String을 사용하는 것이 좋지 않은지, String Builder와 String Buffer와는 어떻게 다른지 알아보겠습니다.

     

    String 클래스

     

    우선 String 클래스의 내부 구조를 보겠습니다.

    String 클래스 내에 문자열을 저장하는 변수를 보면 final char 타입의 배열로 선언되어있음을 알 수 있습니다.

    final 키워드로 선언되었기 때문에, 최초에 이 변수에 저장된 데이터는 변경될 수 없음을 의미합니다.

     

    따라서, String 타입의 변수를 선언해 문자열을 저장한 후에는 변수의 값을 변경할 수 없고 새로운 객체를 생성해야 한다는 것입니다.

     

     

    public class TestString {
    	
    	public static void main(String[] args) {
        
    		String a = new String("ABC");
    		System.out.println("a : "+a);
    		System.out.println(Integer.toHexString(a.hashCode()));
    		a+="DEF";
    		System.out.println("a : "+a);
    		System.out.println(Integer.toHexString(a.hashCode()));
    
    }

    결과

    보시는 것처럼 초기에 "ABC"를 저장했을 때의 주소값과 += 연산자를 이용해서 데이터를 변경했을 때의 주소 값이 다른 것을 확인할 수 있습니다.

     

    앞선 포스팅 내용에서 언급했듯이 Object타입의 변수에는 데이터 값이 직접 저장되지 않고, heap메모리에 저장된 데이터의 주소 값이 저장됩니다. String타입은 primative타입이 아닌 object타입에 속하기 때문에 위 코드에서 문자열 "ABC"는 heap메모리에 저장되고 String 타입 변수 a에는 그 주소 값이 저장됩니다.

     

    이후 a변수의 문자열에 "DEF"를 추가하기 위해 a+="DEF" 다음과 같은 코드를 실행하게 되면, heap메모리에 "ABCDEF"라는 문자열을 저장한 후 그 메모리 주소값을 a변수에 담게 됩니다. String타입 변수의 값은 final로 선언되어 변경할 수 없기 때문이죠.

     

     

    String Buffer/String Builder

     

    그렇다면 String Buffer와 String Builder는 어떨까요? 앞서 String클래스로 했던 대로 코드를 작성해보겠습니다.

     

    public class TestString {
    	
    	public static void main(String[] args) {
        
    		StringBuffer b = new StringBuffer("ABC");
    		System.out.println("b : "+b);
    		System.out.println(Integer.toHexString(b.hashCode()));
    		b.append("DEF");
    		System.out.println("b : "+b);
    		System.out.println(Integer.toHexString(b.hashCode()));
            
            System.out.println("----------------------------------------------");
    		
    		StringBuilder c = new StringBuilder("ABC");
    		System.out.println("c : "+c);
    		System.out.println(Integer.toHexString(c.hashCode()));
    		c.append("DEF");
    		System.out.println("c : "+c);
    		System.out.println(Integer.toHexString(c.hashCode()));
    
    }

    결과

    보시는 것처럼, append()메소드를 이용해 "ABC"에서 "ABCDEF"로 값을 변경했지만 여전히 같은 값을 참조하고 있음을 알 수 있습니다.

     

    String 클래스가 값이 변경될 때 새로운 메모리 공간을 할당받아 참조되지 않는 데이터를 생성하게 되는 반면, StringBuffer/String Builder는 변경되는 값의 길이에 따라 메모리 공간을 확장해 데이터를 저장합니다.

    이로써,  String 클래스는 StringBuffer/String Builder에 비해 문자열의 조작이 빈번하게 일어나는 경우 메모리 효율이 떨어진다는 결론을 내릴 수 있습니다.

     

     

    String Buffer 와 String Builder의 차이점

     

    String Buffer와 String Builder. 이름도 비슷하고 append()라는 이름의 메소드를 사용하고, 하는 짓도 비슷해 보이는 이 두 클래스는 어떤 차이가 있을까요?

     

    가장 큰 차이점은 Multi thread환경에서의 동기화 여부입니다.

     

    String Buffer는 Multi thread 환경에서 synchronization이 적용됩니다. 즉, thread-safe하다고 할 수 있습니다. 반면, String Builder는 Multi thread환경에서 동기화되지 않습니다.

     

    다시 말해, Multi thread환경에서 String Buffer클래스에는 여러개의여러 개의 thread가 동시에 접근할 수 없고, String Builder클래스에는 여러 개의 thread가 동시 접근이 가능하다는 것입니다.

     

    이러한 점에서 단일 thread환경을 기준으로, String Builder의 속도가 String Buffer의 속도보다 빠릅니다. 동기화를 고려하지 않기 때문이죠.

     

     

Designed by Tistory.