String vs StringBuffer vs StringBuilder

yoon·2022년 5월 31일
0

1. String

String 객체는 불변 객체(값)이다.

1-1. String Constant Pool

String 에 값을 할당하는 방법은 2가지가 있다.

  • 리터럴 변수를 대입
String str = "abc";

String 을 리터럴 값으로 할당하게 되면, Heap 메모리 영역 안의 특별한 메모리 공간인 String constant pool 에 저장된다.

만약 String constant pool 에 존재하는 리터럴 값을 사용하면, 새로운 리터럴 값을 만드는게 아닌 현재 존재하는 값을 사용하게 된다. 따라서, 아래와 같은 결과를 볼 수 있다.

String str1 = "abc";
String str2 = "abc";
System.out.println(str1 == str2) // true
  • new 키워드를 사용
String str = new String("abc");

new 키워드를 통해 값을 할당하면, Heap 메모리 영역 안에 동적으로 메모리 공간이 할당 된다.

같은 문자열이더라도 new 키워드를 통해 String 객체를 생성하면, Heap 영역 안의 다른 메모리 공간을 참조하게 된다. 따라서, 아래와 같은 결과를 볼 수 있다.

String str1 = new String("abc");
String str2 = new String("abc");
System.out.println(str1 == str2) // false

1-2. String 객체를 이용한 문자열 연산

String 은 불변 객체이므로, 아래와 같이 변경이 일어날 경우 객체 안의 값이 변경되는 것이 아니라 새로운 객체가 생성된다.

연산이 수행될 때 마다 두 문자열을 모두 읽어 들이고, 새로운 메모리에 복사를 하기 때문에 성능이 좋지 않다.

String str1 = "abc"; // value: abc, address: 1111
String str2 = "def"; // value: def, address: 2222
str1 = str1 + str2 // value: abcdef, address: 3333

이전에 참조하던 address: 1111 객체는 쓰레기가 되고 나중에 GC 에 의해 처리된다.

2. StringBuffer, StringBuilder

StringBufferStringBuilderAbstractStringBuilder 라는 추상 클래스를 상속받아 구현되어 있는 가변 클래스이다.

AbstractStringBuilder 추상클래스에는 2가지 멤버 변수가 존재한다.

  • value
    문자열의 값을 저장하는 byte형 배열
  • count
    문자열 크기의 값을 가지는 int형 변수

2-1. AbstractStringBuilder를 이용한 문자열 연산

예시를 통해 문자열 연산 과정을 간략히 보면 다음과 같다.

StringBuilder sb = new StringBuilder();

StringBuilder 를 생성할 때 capacity 를 지정하지 않으면 기본 16으로 설정된다.

  • value의 크기는 16, 값은 비어있다
  • count는 0으로 초기화
sb.append("first string");
  • "first string" 문자열의 크기는 12이다. 기존 value 가 비어 있었고, 문자열의 크기가 12보다 작으니 문자열 복사 없이 바로 배열에 추가가 된다
  • value 의 값은 "first string"
  • count는 12로 갱신된다
sb.append("second string");
  • "second string" 문자열의 크기는 13. value에 남아 있는 공간이 4이므로 배열의 크기를 늘려줘야 한다
  • value 크기를 두배(32)로 늘리고 기존의 문자열을 복사한다. 그 후, 새로운 문자열을 더해준다.
  • count 는 25로 갱신

String 과 달리, 매번 문자열을 복사하고 메모리를 할당하는 과정이 없어 성능상 이점이 존재한다.

2-2. StringBuffer vs StringBuilder

StringBuffer는 synchronized 키워드를 사용하여 동기화를 지원한다. 즉, 멀티 스레드 환경에서도 안전하게 동작할 수 있다.

StringBuilder 는 동기화를 지원하지 않는다. thread safe 하지 않지만, StringBuffer 보다 성능상의 이점을 갖는다.

0개의 댓글