[자바] String은 어떻게 관리되나요?

skyepodium·2021년 12월 31일
1

1. 생성

자바에서 String를 객체를 생성하는 방법은 크게 2가지 입니다.

첫번째는 리터럴(따옴표)을 이용하는 것이며, 두번째는 String 클래스의 생성자를 이용하는 방식이며,

// 1. 리터럴 방식
String b = "hello";

// 2. String 클래스의 생성자 방식
String a = new String("hello");

이펙티브 자바에 따르면, 생성자를 이용하는 방식은 절대 하지 말라고 합니다.

2. String Constant Pool

리터럴 방식 - String Constant Pool 영역에 생성
생성자 방식 - 객체를 Heap 영역에 생성

리터럴 방식의 경우 String Constant Pool을 먼저 조회하고 hello문자열을 검색합니다. 없으면 생성하고, 만약 있다면 또 생성하지 않고 주소값을 참조합니다.

생성자 방식의 경우 객체를 생성할때마다 heap영역에 저장됩니다.

3. 주소 비교

리터럴 방식의 경우 같은 주소를 참조하기 때문에 주소값 비교가 true, 생성자 방식의 경우 false 입니다.

class Main {
    public static void main(String[] args) {

        // 1. 리터럴 방식
        String a = "hello";

        String b = "hello";

        // 2. String 클래스의 생성자 방식
        String c = new String("hello");

        String d = new String("hello");

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

4. intern()

String 클래스에는 intern 메소드가 있습니다. 템플릿 리터럴로 생성될때 내부적으로 수행됩니다.

intern은 해당 객체가 String Constant Pool에 있는지 검사하고 없으면 추가 하고 참조값을 리턴, 있으면 객체를 반환합니다.

class Main {
    public static void main(String[] args) {

        // 1. 리터럴 방식
        String a = "hello";

        String b = "hello";

        // 2. String 클래스의 생성자 방식
        String c = new String("hello");

        String d = new String("hello");

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

        c = c.intern();
        d = d.intern();
        System.out.println(a == c); // true
        System.out.println(c == d); // true
    }
}

5. 정리

자바에서 문자열을 생성할때 반드시 리터럴을 사용합시다.

생성자 방식은 쓸데없는 인스턴스를 생성하지만, 리터럴 방식은 객체를 재사용함이 보장되어 메모리를 효율적으로 사용할 수 있습니다.

profile
callmeskye

0개의 댓글