String str = "Hello";
System.out.println("String 객체의 주소 : "+str.hashCode());
str = str + " World";
System.out.println("String 객체의 주소 : "+str.hashCode());
리터럴로 선언한 문자열 객체의 주소를 출력하고, 문자열만 더한 다음 객체 주소를 다시 출력해 보는 코드이다.
다시 변수를 만든 것도 아닌데 주소가 같지 않을까?
String 객체의 주소 : 3541040
String 객체의 주소 : 1758230625
하지만 아니다.
왜일까?
자바에서 String 객체는 기존 객체를 재사용하지 않는다, 같은 객체에 더한다고 해도 새로운 객체가 생성되고 기존 객체는 GC의 대상이 된다.
즉, String 클래스는 Immutable, 불변성을 갖는다.
그래서 변경이 자주 일어나는 프로그램에서 String만 사용하게 되면 효율적인 성능을 기대하기 어렵다.
이 단점을 보완하기 위해 나온 클래스가 StringBuffer와 StringBuilder다.
StringBuffer와 StringBuilder
public final class StringBuffer
extends AbstractStringBuilder
implements Serializable, Comparable<StringBuffer>, CharSequence
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, Comparable<StringBuilder>, CharSequence
StringBuffer
와 StringBuilder
두 클래스 모두 AbstractStringBuilder
라는 추상 클래스를 상속받고 있다.
AbstractStringBuilder
추상 클래스의 멤버 변수엔 2가지 변수가 존재한다.
byte[] value; //The value is used for character storage.
int count; //The count is the number of characters used.
두 클래스 모두 문자열을 수정할 때 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;}
문자열을 추가하게 되면 추가할 문자열의 크기(길이)만큼 현재의 문자열을 저장하는 배열의 크기를 늘려주고,
그 공간에 문자열을 넣어주는 방식이다.
즉, 같은 주소공간을 참조하며 값이 변경되기 때문에 두 클래스는 Muttable, 가변성을 가진다.
이 두 클래스에서도 차이점이 존재하는데 바로 동기화(Synchronization)이다.
@Override
@HotSpotIntrinsicCandidate
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;}
StringBuffer는 메서드에서 synchronized
키워드를 사용하기 때문이다.
synchronized
키워드는 자바에서 동기화를 구현하는 키워드로, synchronized 블록을 사용하고 있는 스레드 외에 다른 스레드가 접근할 수 없도록 차단하는 것이다.
즉, 여러 스레드의 동시 접근을 막아 멀티스레드 환경에서 데이터의 일관성을 보장할 수 있다.
StringBuilder는 동기화가 없어 멀티스레드 환경에서 안전하지 않지만, 그로 인한 성능 저하가 없어 단일 스레드에서 더 빠르다.
문자열의 추가, 수정, 삭제 등 변경이 빈번한 경우 각각 언제 사용하는 게 좋을까?
- StringBuffer - 멀티스레드 환경
- StringBuilder - 단일스레드 환경
참고
'💻 Dev > Java' 카테고리의 다른 글
자바는 Call by Value만 사용한다. (0) | 2024.11.22 |
---|---|
String Constant Pool, feat. Runtime Constant Pool (0) | 2024.11.02 |
BigDecimal이란? (0) | 2024.10.30 |
자바 코드의 메모리 영역(스택&힙) (0) | 2024.10.29 |
JVM 구조와 동작 과정 (0) | 2024.10.29 |
예외(Checked Exception, Unchecked Exception) (0) | 2024.10.26 |