Java에서 일반적으로 객체를 생성할 때 new 키워드를 사용합니다. 그러나 문자열은 특이하게도 new 키워드 뿐만 아니라 바로 값을 할당할 수도 있는데 이를 문자열 리터럴이라고 부릅니다.
public void string() {
String name = "lxxjn0"; // 문자열 리터럴 생성
String name1 = new String("lxxjn0"); // new 연산자를 이용한 문자열 생성
}
new 키워드 방식과 문자열 리터럴 방식은 문법적 차이 뿐만 아니라 실제 메모리에 할당되는 영역에도 차이가 있습니다.
public void string() {
String name = "lxxjn0";
String name1 = "lxxjn0";
String name2 = new String("lxxjn0");
String name3 = new String("lxxjn0");
}
문자열 리터럴의 경우 내부적으로 String의 intern() 메서드를 호출합니다.
intern()메서드는 String Constant Pool에 생성하려는 문자열이 이미 존재할 경우 주솟값을 반환하고 없다면 새로 객체를 생성한 후 주솟값을 반환합니다.
/**
* Returns a canonical representation for the string object.
* <p>
* A pool of strings, initially empty, is maintained privately by the
* class {@code String}.
* <p>
* When the intern method is invoked, if the pool already contains a
* string equal to this {@code String} object as determined by
* the {@link #equals(Object)} method, then the string from the pool is
* returned. Otherwise, this {@code String} object is added to the
* pool and a reference to this {@code String} object is returned.
* <p>
* It follows that for any two strings {@code s} and {@code t},
* {@code s.intern() == t.intern()} is {@code true}
* if and only if {@code s.equals(t)} is {@code true}.
* <p>
* All literal strings and string-valued constant expressions are
* interned. String literals are defined in section {@jls 3.10.5} of the
* <cite>The Java Language Specification</cite>.
*
* @return a string that has the same contents as this string, but is
* guaranteed to be from a pool of unique strings.
*/
public native String intern();
자바 소스 파일(.java)이 클래스 파일(.class)로 컴파일되고 JVM(Java Virtual Machine)에 올라갈 때, JVM은 String Constant Pool에 동일한 문자열이 있는지 확인하고 이미 존재한다면 재사용을 하고 없는 경우 새로운 문자열을 만듭니다.
문자열 리터럴은 이와같이 String Constant Pool에서 상수처럼 취급되기 때문에 불변(immutable) 하며 thread-safe 합니다.
추가적으로 String으로 연산을 하는 경우 문자열 변경되면 기존의 불변 객체를 수정하는 것이 아닌 새로운 객체를 만들게 됩니다.
기존 문자열은 참조가 사라지게 되고 가비지 컬렉터(Garbage Collector)의 수집 대상이 되는데 이와 같은 일련의 과정은 의도치 않은 Java 성능 이슈를 유발할 수 있습니다.
출처