Java에서 문자열을 다룰 때 사용하는 클래스로는 String, StringBuilder, StringBuffer가 있습니다.
연산이 많지 않을때는 3 클래스 중 어떤 클래스를 사용하더라도 문제가 없지만, 연산 횟수가 많아지거나 멀티스레드, Race Condition 등의 상황이 자주 발생하면 각 클래스의 특징을 이해하고 상황에 맞는 적절한 클래스를 사용해야 합니다.
String vs StringBuilder, StringBuffer
String과 StringBuilder, StringBuffer의 가장 큰 차이점은 불변성(Immutable)입니다.
String str1 = "Hello";
str1 = str1 + "World";
String은 리터럴(literal) 방식으로 생성하면 Heap 영역 내 String constant Pool에 저장됩니다. 이때 str1 참조변수에 + 연산자를 이용해 "World" 문자열을 붙이면 str1이 "Hello World"로 값이 변경된 것이라 생각할 수 있지만, 실제로는 "Hello World" 라는 값을 가지고 있는 새로운 주소를 가리키게 변경된 것입니다.
String은 불변하기 때문에 문자열을 수정하게 되면 Heap 메모리 내의 문자열 값을 수정하는 것이 아닌 새로운 주소를 가리키게 되고, 기존 값은 GC(Garbage control)에 의해 제거됩니다. 때문에 변하지 않는 문자열을 자주 읽어들이는 경우에 사용하기 좋지만, 문자열의 수정, 삭제 등이 빈번하게 발생하면 Heap 영역에 임시 가비지(Garbage)가 생성되어 메모리 부족으로 성능이 낮아집니다.
이를 해결하기 위해 Java에서 사용하는 것이 StringBuffer, StringBuilder 클래스로 가변성(mutable)을 가지고 있습니다.
String과 반대로 StringBuffer, StringBuilder는 가변성을 가지고 있기 때문에 append(), delete() 등의 API를 이용해 동일 객체 내에서 문자열을 변경하는 것이 가능합니다.
StringBuilder vs StringBuffer
StringBuilder와 StringBuffer는 둘 다 가변성을 가지고 있고 동일한 API를 가지고 있으며 String Constant Pool이 아닌 Hep 영역에 생성되며, 차이점으로는 동기화 지원 여부가 있습니다.
StringBuilder는 동기화를 지원하지 않아 멀티쓰레드 환경에서 사용하기 적합하지 않지만, 때문에 단일쓰레드에서의 성능은 StringBuffer보다 뛰어납니다.
StringBuffer는 동기화를 지원해 멀티쓰레드 환경에서의 안정성을 가지고 있습니다.
정리
- String
- 멀티쓰레드 환경
- 문자열 연산이 적은 환경
- StringBuilder
- 스레드에 안전한지 여부가 관계 없는 프로그램 개발 시
- 문자열 연산이 많은 단일스레드 환경
- StringBuffer
- 스레드에 안전한(thread-safe) 프로그램이 필요하거나, 개발 중인 시스템의 부분이 시스템에 안전한지 모를 경우
- 문자열 연산이 많은 멀티스레드 환경