자바에서 문자열을 다룰 때 String, StringBuilder, StringBuffer 클래스를 사용하게 된다.
보통 개발할 때 String을 많이 사용했는데, 이 세가지가 분명한 차이점과 쓰임이 있다는 걸 알게 됐다.
String
String에 값을 할당하면 Heap의 String Constant Pool에 저장된다.
그 값을 변화할 경우에는 String Class에서 새로운 String 객체를 생성하는 것이고, 기존 객체는 GC에 의해 제거된다.
String이 불변성(immutable)을 갖고있기 때문이다.
따라서, 자주 변하는 객체를 String으로 생성하면 효율성이 떨어진다.
연산이 자주 일어나는 경우에는 StringBuilder와 StringBuffer를 사용하는 게 바람직하다.
AbstractStringBuilder
StringBuilder와 StringBuffer은 AbstractStringBuilder 추상클래스를 상속받아 구현했기 때문에 가변성(mutable)을 갖는다는 공통점이 있다.
AbstractStringBuilder는 값을 저장하는 byte형 배열인 value와 문자열의 크기를 저장하는 int형 변수인 count 두 가지의 멤버변수가 있다.
AbstractStringBuilder에 문자를 추가하고 싶을 땐 append() 메서드를 이용한다.
public AbstractStringBuilder append(String str) {
if (str == null) {
return appendNull();
}
int len = str.length();
ensureCapacityInternal(count + len);
putStringAt(count, str);
count += len;
return this;
}
이런 내부구조로 인해 값이 변경되더라도 기존과 같은 주소를 참조하게 되는 것이다.
StringBuilder와 StringBuffer
그렇다면 둘은 어떤 차이가 있고, 각기 어떤 상황에서 쓰이는 걸까?
둘의 차이점은 '동기화(Synchronization)'에 있다.
StringBuilder는 동기화를 지원하지 않고, StringBuffer는 동기화를 지원하기 때문에, 동기화가 필요한 상황에서는 StringBuffer가 더 적합할 것이다.
하지만 StringBuilder가 성능 면에서는 StringBuffer보다 우수하기 때문에 단일 스레드 환경에서는 StringBuilder를, 멀티 스레드에서는 StringBuffer를 사용하는 게 좋다.
왜 동기화(synchronized 키워드)가 걸려있으면 느린 걸까?
동기화가 걸려있으면 오직 하나의 쓰레드만 자원에 접근이 가능하다. 동기화가 걸려있는 메소드나 블록이 실행되는 동안에는 동기화된 다른 쓰레드는 lock이 걸려 해당 자원을 사용할 수 없기 때문이다.
정리
정리하자면, 변하지 않는 문자열을 자주 사용하는 경우 String, 값이 자주 변하는 문자열을 사용하는 경우 단일 스레드에서는 StringBuilder, 멀티 스레드에서는 StringBuffer를 사용하는 것이 좋다.
Reference ▼
'개발공부 > JAVA' 카테고리의 다른 글
Thread (0) | 2023.05.24 |
---|---|
[JAVA] ArrayList 내부 구현 (0) | 2022.09.26 |
[JAVA] System.out.println()을 쓰면 안 되는 이유 (1) | 2022.09.26 |
[JAVA] equals() 와 hashCode() (0) | 2022.09.21 |
[JAVA] 메모리 구조(Stack/Heap) (2) | 2022.09.21 |
댓글