Programming Language/Java

[Java] String Constant Pool

장쫄깃 2022. 6. 12. 23:34
728x90


String Constant Pool


흔히 new 연산자로 String 객체를 생성하지 않는 것이 좋다는 말을 볼 수 있다.

 

String literal로 생성하면 해당 String 값은 Heap 영역 내 "String Constant Pool"에 저장되어 재사용되지만, new 연산자로 생성하면 같은 내용이라도 여러 개의 객체가 각각 Heap 영역을 차지하기 때문이다.

 

그림으로 살펴보자.

 

  • String literal로 생성한 객체는 String Pool 영역에 들어간다.
  • String literal로 생성한 객체의 값이 이미 String Pool에 존재한다면, 해당 객체는 String Pool의 reference를 참조한다. 그림에서 s1과 s2가 같은 곳을 바라보는 이유도 이 때문이다.
  • new 연산자로 생성한 객체는 같은 값이 String Pool에 이미 존재하더라도, Heap 영역 내 별도의 객체를 가리키게 된다.
만약 s1을 Dog로 수정한다면, String Pool 안에 있는 Cat 객체가 Dog로 수정되는 것이아니라 Dog reference를 바라본다. 때문에 자바에서 String은 불변객체이다.
(실제 메모리 내 값이 바뀌지 않기 때문)

 

 

==연산자 vs equals()


위 예제코드를 통해 String의 동일 여부를 체크하는 방식을 알아보자.

 

자바에서 동일성을 체크하는 방법은 크게 ==연산자equals()가 있다.

  • ==연산자
    • primitive type : 값 비교
    • reference type : 주소 비교
  • equals()
    • 내부적으로는 ==연산자와 동일
    • 그러나 String 내부에서 사용하는 equals()는 주소 비교가 아닌 값 비교

 

때문에, s1 == s3 은 false이지만 s1.equals(s3)는 true이다.

equals() 메소드는 최상위 클래스인 Object에 포함되어있는 메소드이다. 그리고 Java에서 Object를 상속받아 새로운 데이터 타입을 만든다면, toString, equals 등의 메소드를 재정의 해서 사용하도록 권장한다. String 클래스에서도 equals() 메소드를 재정의해서 사용한다.

 

가장 중요한 포인트는 ==연산자는 주소값이 같은지 비교하는 것이고, equals()연산도 내부적으로 주소값을 비교하지만 String 클래스에서는 equals()를 재정의해 값을 비교하게 되어있다.

 

 

String interning


String 클래스에는 intern() 이라는 메소드가 있다.

 

intern()은 해당 String과 동등(equal; 값이 같음)한 String 객체가 이미 String Pool에 존재하면 그 객체를 그대로 리턴한다. 그렇지 않으면, 호출된 String 객체를 String Pool에 추가하고 객체의 reference를 리턴한다.

 

String someStr = "intern String";
String newStr = new String("intern String");

String internStr = newStr.intern(); // String Pool Referense return

 

 


참고

https://starkying.tistory.com/entry/what-is-java-string-pool

https://www.baeldung.com/java-string-pool

728x90