String, StringBuffer, StringBuilder는 Java에서 문자열을 관리하는 Class이다.
이들은 변경 가능 여부(mutable or immutable)에 따라
변경불가능한 String 과 변경가능한 StringBuffer,StringBuilder 로 나뉜다.
여기서 말하는 변경 불가능하다는 뜻은 +,concat 같은 문자열 연산이 이루어진 경우
기존에 할당된 메모리 공간을 변경하는 것이 아니라 매번 새롭게 재할당이 이루어진다는 것을 의미한다.
예를 들어 아래 와 같이 String 타입의 str 변수에 "a"를 할당 후, 문자열 연산을 해준 경우
str = "ab" 가 되지만 기존에 "a" 로 할당되었던 공간이 바뀐 것이 아니라 "ab"라는 새로운 공간에 할당을 한다.
String str = "a";
str +="b";
(기존에 "a"로 할당된 공간의 경우 GC(가비지 콜렉터)가 제거하게 된다.) (Heap 영역에 있기 때문)(String,StringBuilder,StringBuffer 모두 Heap 영역에 있다.)
따라서 String 클래스로 문자열 연산이 많이 하는 경우 성능에 이슈가 있을 수 있다. (문자열 연산이 적은 곳에서 강점)
하지만 매번 새롭게 재할당을 하기 때문에
멀티 스레드 환경에서 동기화를 별도로 고려하지 않고 사용해도 무방하다. (멀티스레드 환경에서 강점)
StringBuffer, StringBuilder 의 경우 변경가능하기 때문에
문자열 연산이 일어나는 경우, 매번 재할당 하는 것이 아니라 할당된 메모리 공간의 크기를 변경하는 방식으로 동작한다.
StringBuffer의 경우는 Thread-Safe 하고(멀티 스레드 환경에서 문자열 연산이 많은 경우 강점)
StringBuilder의 경우 Thread-Safe 하지 않다. (싱글 스레드 or 스레드 상관없는 환경에서 문자열 연산이 많은 경우 강점)
문자열 연산이 많은 경우에 단순 성능만 놓고 보면 StringBuilder > StringBuffer >> String 이다.
그 이유는 기본적으로 StringBuilder,StringBuffer가 매번 재할당을 하지 않기 때문에 기본적으로 String 보다 빠르고,
StringBuffer는 Thread-Safe을 보장하기 위해 추가적으로 확인하는 연산이 추가되기 때문이다.
여담으로 JDK 1.5 이전에서는 String을 사용하는 경우 문자열 연산이 많은 경우 성능상의 이슈가 있었지만
JDK 1.5 이후 부터는 컴파일 타임에 String 을 StringBuilder로 컴파일 되록 변경되었기 때문에 String을 사용해도 StringBuilder 와 성능차이가 없어졌다.
다만 반복루프를 사용해서 문자열을 더하는 경우에는 계속 새로운 메모리에 할당되기 때문에, 위의 차이를 이해하고 사용하는 것이 좋다.
따라서 String 을 사용하는 것보다 스레드와 관련히 있으면 StringBuffer를 사용하고, 아니면 그냥 StringBuilder를 사용하는 것을 권장한다.