Language/Java

String.intern() 이란? 언제 사용하는가?

이웃비 2020. 12. 10. 15:00

 

우리는 String 문자열 비교 시 흔히 equals()를 사용하지만, 메모리나 속도를 고려해 == 연산자를 사용하는 경우를 보게 됩니다.

이 때에 사용되는 메서드가 intern()인데요. intern() 은 무엇이고 어떻게 쓰일까요? 그전에 String pool에 대한 이해가 필요합니다.

 

 

String pool 이란?

 

Pool 하면 보통 수영장 풀, 풀장 등을 떠올리실 텐데요. 이처럼 String pool 하면 string이 존재하는 영역을 생각하시면 될 것 같습니다. 같은 String이지만 생성 방식에 따라 차이가 있어 문자열 비교 시 혼란을 주기도 하는데요. 다음 예제를 통해 설명해보겠습니다.

 

String a = "apple";
String b = new String("apple");
String c = "apple";
String d = new String("apple");

System.out.println(a==b); // false
System.out.prrintln(a==c); // true

 

첫 번째 줄에서 String a가 생성될 때, 'apple'은 리터럴 문자열이므로 Heap영역 중에서 String pool에 위치하게 됩니다.

두 번째 줄에서 String b는 new연산자를 통해 객체를 생성합니다. Heap영역에 위치하지만 String pool이 아닌 다른 주소값을 참조합니다.

'=='연산자는 같은 메모리를 참조하는가를 비교합니다. 때문에  a와 b의 비교(a==b)는 false를 반환하게 됩니다.

그렇다면 c는 어떨까요? c가 가리키는 'apple'을 String pool에 넣으려고 보니 이미 'apple'이 존재합니다. 그러면 c는 a와 같은 String pool의 'apple'을 가리키게 됩니다.

a와 c가 같은 값을 참조하므로 a==c는 true를 반환합니다.

이를 그림으로 표현해보면 다음과 같습니다.

 

intern() 의 사용

그렇다면 intern()은 언제 사용할까요? 앞서 설명드렸듯이, 문자열 비교에는 equals()을 흔히 사용합니다. 그렇지만 속도나 메모리 향상을 위해 ==연산자의 사용이 필요할 때가 있습니다. 그럴 때 사용하는 것이 intern() 입니다. 다음 예시를 보시죠.

 

String a = "apple";
String b = new String("apple");
String c = b.intern()

System.out.println(a==b); // false
System.out.prrintln(a==c); // true

 

a와 b의 비교는 앞서 예시처럼 참조하는 위치가 다르므로 false를 반환합니다. 그렇다면 a와 c는 어떨까요? 

intern() 메서드는 String pool에서 리터럴 문자열이 이미 존재하는지 체크하고 존재하면 해당 문자열을 반환하고, 아니면 리터럴을 String pool에 넣어줍니다.

때문에 c의 경우 b의 값인 'apple'이 String pool에 이미 존재하는가를 찾고, 이미 존재하므로 해당 문자열을 반환해 c='apple'이 되는 것입니다.

a와 c는 결국 같은 주소를 참조하게 되어 a==c는 true가 됩니다.

 

이해가 되셨나요?

 ** 참고로 String pool은 Java 7부터 heap영역에 들어가게 되었다고 합니다. 이전(java 6 이하) 버전에서는 Perm 영역에 존재했는데, Perm영역은 사이즈가 고정되어 있어 String 값이 커지면 OutOfMemoryException 문제가 있었다고 하네요. Java6 이하 버전을 사용하는 개발자분들은 참고하시면 좋을 것 같습니다.