티스토리 뷰

JAVA/JAVA기본

JAVA - String Constant Pool이란

realizers 2022. 5. 15. 15:25
728x90
반응형

String Constant Pool


자바에서 String 객체를 생성하는 방법은 따옴표(")를 이용한 방법과 new 연산자를 이용하는 방법이 있습니다. 이 두 방법의 차이에 대해서 한번 알아 보겠습니다.

 

💡 바로 예제 코드를 보며 살펴보겠습니다.

public static void main(String[] args) {
    String text1 = "Java";
    String text2 = "Java";
    String text3 = new String("Java");

    System.out.println("1. text1 == text2은 같을까? " + (text1 == text2)); // true
    System.out.println("2. text1 == text3은 같을까? " + (text1 == text3)); // false
    System.out.println("3. text1.equals(text3)은 같을까? " + (text1.equals(text3))); // true
}

Case 1 - 리터털로 생성한 객체
  • 리터럴로 생성한 객체는 Heap영역 중에서도 String Constant Pool에 할당이 되게 됩니다.
  • 리터럴로 생성한 객체의 값이 이미 String Constant pool에 존재한다면, 해당 객체는 String Pool의 주소값을 참조하게 됩니다. 위의 그림에서 text1과 text2가 같은 곳을 가리키고 있는 것도 이러한 이유 때문입니다.
Case 2 - new연산자 생성한 객체
  • new 연산자로 생성한 String 객체는 같은 값이 이미 String Constant Pool에 존재하더라도 Heap 영역 내 별도의 객체를 가리키게 됩니다.

 

💡 text1 == text2은 왜 true일까?

  • == 연산자는 같은 메모리(주소값)을 참조하고 있는가? 에 대한 비교를 하게됩니다. 위의 사진에서 보면 text1과 text2는 값은 주소값을 참조하고 있기 때문에 true의 값이 도출되고 있습니다.

💡 text1 == text3은 왜 false일까?

  • 각각 서로 다른 주소값을 참조하고 있기 때문에 false를 반환하게 됩니다.
결론
  • String 객체를 new 연산자로 생성하면 같은 값이라 할지라고 Heap영역에 매번 새로운 객체가 생성되게 됩니다. 따라서 String이 갖는 불변성이라는 장점을 누리지 못합니다.
  • 메모리를 효율적으로 사용하기 위해서는 항상 따옴표로 String 객체를 생성하는 것이 좋습니다.

 

String.intern() 


💡 왜 모두 true가 출력이 되는걸까?

  • text3은 new 연산자를 사용하여 Heap 영역에 객체를 생성하고 있습니다. 그런데 text1 == text3을 비교한 값이 true가 출력되고 있습니다. 이는 text1과 text3이 같은 주소값을 참조하고 있다는 의미인데 어떻게 된건지 자세히 알아보겠습니다.
  • text3을 new 연산자를 사용하여 객체를 생성했지만 그 다음 라인에서 intern() 메서드를 사용하고 있습니다. 비밀은 intern() 메서드에 숨겨져 있었습니다. new 연산자를 사용하여 생성한 객체라고 할지라도 Constant Pool에 값이 있으면 Pool에 있는 값을 참조하는 객체를 반환합니다. 만약 동일한 문자열이 존재하지 않으면 Pool에 해당 값을 추가하게 됩니다. 따라서 intern() 메서드를 수행한 뒤에 문자열을 equals() 메서드가 아닌 == 으로 동일한지 비교할 수 있습니다.
public static void main(String[] args) {
    String text1 = "Java";
    String text2 = "Java";
    String text3 = new String("Java");
    text3 = text3.intern();

    System.out.println(text1 == text2); // true
    System.out.println(text1 == text3); // 기대값: flase, 실제값: true
    System.out.println(text1.equals(text3)); // true
}

 

 

Java에서 String은 불변(Immutable) 객체이다.


불변 객체란 무엇일까요?

불변 객체란 객체가 생성된 후 내부의 상태가 변하지 않고 계속 유지되는 객체를 말합니다. 즉, 변수에 객체가 한번 할당이 되면, 해당 객체의 참조를 변경할 수도, 내부의 상태를 수정할 수도 없는 것입니다.

Java에서 String객체는 불변성을 가지는데 어떠한 이유로 불변성을 가지는지 살펴보겠습니다.

 

💡 바로 예제 코드를 보며 살펴보겠습니다.

  • 아래 예제 코드에서 String 객체가 생성된 이후 값을 바꾼다고 해서 실제 내부적으로 최초에 생성된 String 객체의 값이 변경된 것이 아닌 새로운 String 객체가 생성되어 그 주소값이 text1변수에 할당되게 됩니다. 즉 이 상태에서는 최초에 생성된 "Java"라는 문자열과 "Hello Java"의 두 객체는 따로 Heap 영역에 생성되어 있는 상태입니다.
public static void main(String[] args) {
    String text1 = "Java";
    System.out.println(text1.hashCode()); // 2301506

    text1 = "Hello Java";
    System.out.println(text1.hashCode()); // 387417328

}

 

String이 갖는 불변 객체인 이유


1. String 객체의 캐싱기능
  • String이 불변 객체로 설계된 이유는 메모리 절약을 위한 캐싱 기능입니다.
  • 예를 들어 어떠한 문자열이 사용자의 요청을 처리할때마다 Heap 영역에 하나씩 생성이 된다면 사용자의 요청 수에 따라서 Heap 영역에 해당 문자열이 생성이 될 것입니다. 이렇게 된다면 메모리를 낭비하게될 가능성이 있습니다.
  • 예를 들어 "Java"라는 문자열을 100번 출력하고 있습니다. 만약 String의 불변성이 없다면 이 코드는 Heap영역에 100개의 String 객체를 생성하게 됩니다. 그러나 불변성으로 인하여 String 객체는 Sring Constant Pool에 단 한번만 생성이 됩니다. 그러나 100번을 출력하고 있기 때문에 변수 자체는 스택상에서 100번 생성되었다가 사라지게 될 것입니다.
  • 그리고 캐싱의 진정한 목적은 메모리 절약도 있지만 속도 향상에 있습니다. 자주 쓰이는 값은 최대한 CPU와 가까운 데이터일수록 처리가 빠릅니다. 보조기억장치보다는 메모리에 메모리보다는 캐시메모리나 레지스터에 있을수록 값을 꺼내오기가 쉽습니다.
public static void main(String[] args) {
    for (int i = 0; i < 100; i++) {
        String text1 = "Java";
        System.out.println(text1.hashCode()); // 2301506
    }
}
2. 보안기능
  • String은 불변성을 가졌기 때문에 중요한 데이터를 문자열로 다루는 경우 강제로 해당 참조에 대한 문자열 값을 바꾸는 것이 불가능합니다. 따라서 보안에 유리합니다.
3. 스레드 안전성
  • String 객체가 변경될 수 없다는 것은 여러 스레드에서 동시에 특정 String객체를 참조한다고 하더라도 안전하다는 것을 의미합니다. 만약 어플리케이션의 여러곳에서 특정 문자열을 참조하고 있을 때 그 값 자체는 절대 변하지 않으므로 안전할 수 있습니다.
  • 물론 String text = "Hello Java"와 같은 문자열을 변경하는 상황에서는 새로운 String 객체를 생성하므로 이전의 "Java"는 그대로 살아 있는 것입니다.

 

참고)

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

https://dololak.tistory.com/699

https://starkying.tistory.com/entry/why-java-string-is-immutable

https://simple-ing.tistory.com/3

 

728x90
반응형