본문 바로가기
Programming & Language/JAVA

Java) String vs StringBuffer vs StringBuilder 어떤 차이가 있을까?

by 몽글구름 2022. 3. 22.

Java에서 문자열을 사용하고자 할 때, 주로 어떤 클래스를 사용하는가?

각각의 특징을 파악하고 적재적소에 사용해보도록 하자!

 

 

1. String

우선 스트링 클래스를 까보았고, 다음과 같이 value의 갑이 final로 지정된 것을 확인할 수 있다. 즉 지정된 값이 변경되지 않는 다는 점이다.

public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
    private final byte[] value;
}

오라클에서 제공하는 공식 문서의 String class 의 상세 내용에서도 확인할 수 있는데, 

값은 생성된 이후 변경되지 않으며, String 객체는 불변의 값이기에 공유가 가능하다고 언급한다. 여기서 말하는 '공유가 가능하다'는 것은 'Constant Pool'을 이용한 공유를 말한다. 

String str1 = "abcde";
String str2 = "abcde";
String str3 = new String("abcde");
System.out.println(str1==str2);  // true
System.out.println(str2==str3);  // false

해당 코드에서 str1과 str2는 서로 다른 객체이기에 hashcode 값이 다른 것이라고 예측할 수 있었겠지만 비교시 true인 것을 확인할 수 있다. 그 이유는 String는 동일한 문자열이 존재하는 경우 Constant Pool에 저장된 객체를 재사용할 수 있기 때문이다. 그러나 new String을 하여 문자열을 생성한 경우 Heap 영역에 새로 할당되어 만들어지는 것이기에 마지막 코드에서 false 값이 출력되게 된 것이다.

따라서 new 연산자를 사용한 String 객체 생성을 피하고, String을 가지고 하는 반복적인 연산은 (+와 같은) 객체를 지속적으로 할당하기에 StringBufferStringBuilder를 사용하는 것을 추천한다.

 

 

2. StringBuilder

String 클래스와 달리 StringBuilder는 문자열의 변경이 가능하다. String에서 발생하는 성능적 이슈를 해결하기 위해 실제로 JDK 1.5 이상에서는 컴파일 단계에서 String이 내부적으로 StringBuilder로 연산된다고 한다. 

String result1 = str1 + str2;
String result2 = new StringBuilder(String.valueOf(str1)).append(str2).toString();

오라클 문서에 따르면 StringBuilder와 StringBuffer의 API는 서로 호환되나 StringBuilder는 동기화를 보장하지 않는다고 설명한다. 그러나 동기화를 보장하지 않더라도 단일 쓰레드의 환경에서는 StringBuilder가 StringBuffer보다 성능적 측면에서 우수하다고 한다. 

 

 

3. StringBuffer

StringBuffer 또한 String과 달리 문자열 변경이 가능하며, 위에서 언급했듯 'Thread Safe'하다. 즉 멀티 쓰레드의 환경에서 문자열의 연산이 빈번하게 발생하는 경우, StringBuffer를 사용하여, 동기화와 성능을 동시에 해결가능하다.

 

 

4. 그럼 언제 뭘쓸까? 초간단 정리

 

 

참고 자료)

https://docs.oracle.com/javase/10/docs/api/java/lang/String.html

https://docs.oracle.com/javase/10/docs/api/java/lang/StringBuffer.html

https://docs.oracle.com/javase/10/docs/api/java/lang/StringBuilder.html

 

댓글