public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
/** Cache the hash code for the string */
private int hash; // Default to 0
...중략
}
}
위 코드는 java.lang의 포함된 String 클래스이다. 내부적으로 final char 와 int hash를 필드로 가지고 있다. 문자열은 char 배열에 관리되고 있음을 알 수 있다. 그러나 한 가지 주목해야 될 점은 char 배열이 final로 선언되어 있음이다.
내부 value가 final로 선언되어 있기때문에 String 객체는 Immutable하다. 아래 코드를 살펴보자
String url = "http://";
url += "naver.com";
System.out.println(url); // "http://naver.com"
url은 초기에 "http://"로 선언되어 있다. 이후 객체에 저장된 값이 변경되면 내부에 가지고 있는 value값을 변경하는 것이 아니라 "http://naver.com"의 값을 가지는 String 객체를 새로 생성한다. 그렇다면 기존의 "http://" 객체는 어떻게 되는 것일까?
참조를 잃어버려 더 이상 접근 할 수 없는 객체(Garbage)가 되어 GC의 대상이 된다. 이러한 이유로 문자열 연산이 많은 경우에는 성능이 좋지 않다. 그러나 Immutable 함으로 Thread-safe하다는 장점을 가진다.
JDK 1.5 버전 이후에는 컴파일 단계에서 String 객체를 사용하더라도 +연산은StringBuilder로 컴파일 되도록 변경되었다.
String 객체가 가지는 불변성에 따라 발생하는 성능적 이슈를 해결하고자 나온 것이 StringBuffer와 StringBuilder이다. 이 둘은 문자열 객체에 저장된 내용을 변경 할 수 있다. 둘의 차이는 Thread Safe이다. StringBuffer는 멀티스레드 환경에서 동기화를 지원한다. 반면 StringBuilder는 단일 스레드 환경에서 사용하는 것을 권장한다.