프로그래밍/자바(Java)

[ 자바 / JAVA ] String, StringBuilder, StringBuffer 클래스

후르트링 2021. 7. 22. 16:47
728x90

세가지 클래스 모두 자바에서 문자열의 표현을 위한 클래스이지만 차이가 있습니다. 하나씩 각 클래스마다의 특징과 차이점을 정리해보겠습니다.

[String 클래스]

다음과 같이 String을 생성하는 두 가지 방식이 있습니다.

   1. new 연산자를 이용하는 방식
   2. 리터럴을 이용하는 방식

//(1) new 연산자
String str1 = new String("abcd");
//(2) 리터럴
String str2 = "abcd";

 

두가지 방식의 공통점은

  • 한번 생성된 String은 불변입니다.(immutable)
  • String을 연결하면 기존의 String에 연결되는 것이 아닌, 새로운 문자열이 생성됩니다(메모리 낭비)

 

두 가지 방식의 차이는

  • new 연산자로 생성하면 힙(Heap) 메모리에 인스턴스로 생성됩니다.
  • 리터럴 방식은 상수 풀(constant pool)에 있는 주소를 참조하는 방식입니다.
  • 힙 메모리를 사용하는 방식은 다른 주소 값을 가집니다.
  • 아래 코드와 같이 리터럴 방식은 똑같은 문자열에 대하여 같은 주소를 참조하고 있습니다.
public class StringTest {
    public static void main(String[] args) {
        String str1 = new String("java");
        String str2 = new String("java");

        System.out.println(str1 == str2);    //false

        String str3 = "java";
        String str4 = "java";

        System.out.println(str3 == str4);    //true
    }
}

 

[상수 풀(constant pool)]

  • new 연산자를 사용하지 않고 리터럴로 사용하게 되면 상수 풀에 저장이 됩니다.
  • JVM의 Runtime Data Area의 힙(Heap)영역에 있습니다.
  • 만약에 String a = "abc" 라고 선언하고, 다시 String b="abc"로 선언을 하게되면 String b는 이미 상수 풀에 있는 "abc"의 주소 값을 가지게 됩니다.
  • String이 리터럴로 선언한 경우에 String 클래스의 intern() 메소드가 위의 기능을 담당합니다.
  • intern() : 주어진 문자열이 String Constant Pool에 존재하는지 검색하고 있다면 그 주소값을 반환하고 없다면 String Constant Pool에 넣고 새로운 주소값을 반환하게 된다.
  • 즉, 문자열이 동일한 경우에는 하나의 String 인스턴스만 생성해서 공유하게 됩니다.
  • 그러므로 자바에서는 문자열을 복사한다기보다는, 하나의 문자열을 같이 참조합니다.

 

[StringBuilder, StringBuffer]

[공통점]

  • StringBuilder와 StringBuffer모두 변경이 가능한 객체입니다.(Mutable)
  • 그러므로 문자열 연산(concat 등) 할 때 새롭게 객체를 생성하지 않고 원래 사용하던 객체를 사용합니다.
  • 문자열 연산에 아주 유리합니다

[차이점]

  • StringBuffer는 Thread-Safe합니다.
  • StringBuilder는 Thread-Safe하지 않습니다.

 

그러므로 멀티 쓰레드 환경에서는 StringBuffer를, 단일 쓰레드 환경에서는 StringBuilder를 이용하면 됩니다.