본문 바로가기

Java/문법 및 이해

[JAVA] String 객체 생성과 Constant Pool

자바에는 String 객체를 생성하는 방법이 두 가지 있다.

 

물론 생성되는 String 객체는 물론 값이 아닌 객체 즉, heap 영역에 생성된다.

 

String 객체를 생성하는 방법은 스트링 리터럴과 new 연산자를 이용한 객체 생성 방법이다.

 

간단한 코드를 예시로 두 가지의 차이점을 알아보자.

public class StringTest {
    public static void main(String[] args) {
        String name1 = new String("name");
        String name2 = "name";
        String name3 = "name";
        String name4 = new String("name");

        if (name1 == name3) {
            System.out.println("name1 == name3");
        }
        if (name2 == name3) {
            System.out.println("name2 == name3");
        }
        if (name1 == name4) {
            System.out.println("name1 == name4");
        }
    }
}

name1  ~ 4 까지는 String 객체를 생성한 코드이다.

 

여기서 다른 점은 name1, name4는 new 연산자를 이용해서 String 객체를 생성하였고, name2, name3는 스트링 리터럴을 이용해서 객체를 생성하였다.

 

그리고 if 문으로 스트링 리터럴로 생성한 객체들 끼리 비교해보고 (스트링 리터럴 == 스트링 리터럴), 스트링 리터럴과 new 연산자와 비교(스트링 리터럴 == new), 마지막으로는 new 연산자와 new 연산자를 이용한 비교(new == new) 하여 각 객체의 참조된 값을 확인하려고 한다.

 

name2 == name3

결과는 name2와 name3만 같다고 나온다.

 

왜일까?

 

name2와 name3는 스트링 리터럴로 객체로 생성한 값들이다.

나머지 new 연산자를 이용한 객체 값인 name1과 name4는 같지 않을 뿐더러, 스트링 리터럴과 new 연산자와도 참조 값이 다르다.

 

이유를 설명하기 전에 다른 블로그 분들의 사진을 먼저 확인하자

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

위 사진을 보면, 스트링 리터럴로 생성한 객체들은 heap 메모리 영역에 저장이 되는 것을 확인할 수 있다. 하지만 특이한 점은 String Pool(Constant Pool)이라는 곳에 저장되는 것이다.

 

스트링 리터럴이 Constans Pool에 저장되는 이유는 같은 객체를 다시 선언했을 때, 쓸데 없는 메모리 사용 즉, 중복을 방지하기 위함이다.

같은 객체의 값이 선언되면 Constant Pool에서 그 값을 가져와 재사용한다는 의미이다.

 

반면에, new 연산자를 이용한 객체는 heap 영역에 저장된다.

쉽게 말해 같은 스트링 값일지라도 stack 메모리에서 다른 주소 값을 가지고 있기 때문에 heap 메모리에서 전혀 다른 객체로 보고 있게 되는 것이다.

 

 

결론은...

 name1과 name4는 heap 메모리에 개별 객체가 만들어지고, name2와 name3은 String Constant Pool에 만들어진 하나의 객체를 참조한다. 따라서 총 3개의 String 객체가 생성된다.