문자열 인턴십(String Interning)이란?
문자열 인턴십은 서로 구별되는 모든 문자열 값에 대해 단 하나의 복사본만 저장하는 기법입니다. 자바에서 String 객체는 한 번 생성되면 내용을 변경할 수 없는 불변(immutable) 객체이므로, 동일한 데이터를 가진 여러 문자열이 하나의 메모리 공간을 공유할 수 있습니다. 이러한 방식 덕분에 프로그램 전체의 메모리 사용량을 크게 줄일 수 있습니다.
intern() 메서드 호출 시의 동작
먼저 두 문자열 간의 동등성을 검사합니다. 즉, 해당 문자열 객체가 이미 문자열 상수 풀(String Constant Pool, SCP)에 존재하는지 확인합니다.
풀에 이미 존재한다면 해당 문자열을 풀에서 가져와 반환하고, 존재하지 않는다면 새로운 String 객체를 생성하여 풀에 추가한 뒤 그 객체의 참조값을 반환합니다.
따라서 두 문자열 a, b에 대해
a.intern() == b.intern()이 참일 필요충분조건은a.equals(b)가 참을 반환하는 경우입니다.
예제 코드
public class Demo {
public static void main(String[] args) {
String s1 = new String("Its");
String s2 = s1.concat("sample");
String s3 = s2.intern();
System.out.println("객체 2와 객체 3의 동등성 확인 :");
System.out.println(s2 == s3);
String s4 = "Its a sample";
System.out.println("객체 3과 객체 4의 동등성 확인 :");
System.out.println(s3 == s4);
}
}실행 결과
객체 2와 객체 3의 동등성 확인 : true 객체 3과 객체 4의 동등성 확인 : false
코드 해설
Demo 클래스에는 main 메서드가 정의되어 있으며, 여기서 세 개의 String 객체 인스턴스가 선언됩니다. 첫 번째 문자열 s1은 new 키워드로 생성되어 힙 영역에 새로 할당되고, 두 번째 문자열 s2는 s1에 다른 값을 연결(concat)하여 만들어집니다. 세 번째 문자열 s3는 s2에 대해 intern()을 호출한 결과입니다.
s2와 s3의 경우, intern() 호출 당시 풀에 존재하지 않던 문자열이 상수 풀에 등록되면서 두 변수가 같은 객체를 가리키게 되므로 '==' 비교 결과 true가 출력됩니다. 반면 s4는 리터럴 "Its a sample"로 초기화된 문자열로, s2·s3의 내용("Itssample")과는 다른 별개의 문자열이므로 서로 다른 객체이며, 비교 결과 false가 됩니다.
추가로 알아두면 좋은 점
JDK 7 이전에는 문자열 상수 풀이 PermGen(영구 생성 영역)에 위치했지만, JDK 7부터는 힙 영역으로 이동했습니다. 또한 실무에서는 문자열 비교 시 '==' 연산자보다 equals() 메서드를 사용하는 것이 권장되며, intern()은 동일한 문자열이 대량으로 반복되는 특정 상황에서 메모리 최적화 목적으로 유용하게 활용할 수 있습니다.