개발자는 기록이 답이다

🐙 Primitive 타입과 Reference 타입 본문

언어/Java

🐙 Primitive 타입과 Reference 타입

slow-walker 2023. 12. 21. 16:08

 

Primitive 타입과 Reference 타입의 차이점?

Primitive 타입과 Reference 타입은 Java에서 변수의 성격과 저장 방식에 차이가 있는 두 가지 기본적인 데이터 타입이다.

 

구분 Primitive 타입 Reference 타입
메모리 할당 및 저장 방식 스택 메모리에 직접 값을 저장 참조 주소를 변수에 할당하고, 해당 주소를 따라가서 메모리에 저장된 객체의 값에 접근.
객체는 힙 메모리에 저장됨
(String은 예외로 String Pool에 저장됨)
데이터 크기 고정된 크기를 가짐 4바이트 또는 8바이트의 고정 크기를 가지며, 실제 
기본 타입 목록 byte, short, int, long, float, double, char, boolean  클래스, 인터페이스, 배열 등
값의 초기화 자동으로 기본값으로 초기화 null로 초기화되며, 객체를 생성하여 할당해야 실제 값을 가짐
예시 java int num = 42; java String str = new String("Hello");
주요 특징 값 자체를 변수에 저장하며 빠른 연산 가능 객체의 주소(참조)를 변수에 저장하고 간접적으로 접근하며 유연한 활용 가능

 

String은 String Pool에 저장되는 이유와 String Pool의 동작 원리는?

 

1) String Pool에 저장되는 이유

  • Java에서는 String 리터럴(문자열 상수)을 사용할 때, 동일한 문자열은 메모리 공간을 절약하기 위해 하나의 인스턴스로 관리한다.
  • String Pool은 이러한 중복 문자열을 효율적으로 관리하기 위한 메모리 영역이다.
  • 이미 존재하는 문자열과 동일한 문자열 리터럴을 생성하면, 새로운 객체를 생성하는 대신 기존 객체의 참조를 반환한다.

자세한 내용은 이전에 포스팅한 String의 Constant Pool과 Heap의 차이 를 참고해주세요.

 

2) String Pool의 동작 원리

  • 문자열 리터럴의 등록: 코드 상에서 문자열 리터럴이 사용되면 먼저 String Pool에서 해당 문자열을 검색합니다.
  • 중복 검사: 동일한 문자열이 이미 Pool에 존재하는지 확인하고, 있으면 새로운 객체를 생성하지 않고 기존 객체의 참조를 반환합니다.
  • 새로운 문자열의 경우 등록: Pool에 없는 경우 새로운 객체를 생성하고 Pool에 등록합니다.
String str1 = "Hello"; // String Pool에 "Hello"가 없으면 새로운 객체 생성
String str2 = "Hello"; // String Pool에서 "Hello"를 찾아 기존 객체의 참조 반환

// str1과 str2는 동일한 객체를 참조하고 있음

 

String Pool에서의 중복 문자열 관리(Intern메소드)

+------------------------------------+
|           코드 실행 시작               |
+------------------------------------+
                  |
                  v
+-----------------+------------------+
| 문자열 리터럴 등록                      |
| (코드에 등장하는 문자열)                 |
+-----------------+------------------+
                  |
                  v
+-----------------+------------------+
| String Pool에서 중복 검사             |
| (이미 등록된 문자열인지 확인)             |
+-----------------+------------------+
                  |
    +-------------+-------------+
    | 중복 문자열이 아닌 경우         |
    | (새로운 String 객체 생성)     |
    +-------------+-------------+
                  |
                  v
+-----------------+------------------+
| String Pool에 등록                   |
+-----------------+------------------+
                  |
                  v
+-----------------+------------------+
| 코드에서 문자열 참조                    |
+-----------------+------------------+
                  |
                  v
+-----------------+------------------+
|            코드 실행 종료             |
+-----------------+------------------+

 

 

1) String Pool의 역할

  • String Pool은 JVM 메모리 중 특별한 영역으로, 문자열 리터럴을 관리하는 역할이다.
  • 중복된 문자열을 효율적으로 관리하여 메모리 공간을 절약합니다.

2)중복 문자열의 처리

  • 문자열 리터럴이 등록될 때, JVM은 먼저 해당 문자열이 String Pool에 이미 존재하는지 확인다.
  • 중복된 문자열이 없으면 새로운 문자열 객체를 생성하고, Pool에 등록다.
  • 중복된 문자열이 이미 Pool에 존재하면 해당 객체의 참조를 반환한다.

 

3) intern() 메소드

  • intern() 메소드를 호출하면 문자열을 String Pool에 등록하고, 이미 등록된 경우 기존 객체의 참조를 반환한다.
  • 이를 통해 직접적으로 String Pool에 문자열을 등록할 수 있다.
String str1 = "Hello";
String str2 = "Hello";
String str3 = new String("Hello").intern();

// str1과 str2는 동일한 객체 참조
System.out.println(str1 == str2); // true

// str1과 str3도 동일한 객체 참조 (intern() 메소드로 인해 String Pool에 등록)
System.out.println(str1 == str3); // true

 

 

객체는 힙 영역,  String 클래스는 String Pool에 저장되는데, String Pool의 위치는?

  • String Pool은 힙 영역에 위치하며, String Constant Pool이라고도 불린다.
  • 따라서 String Pool은 힙 영역 내에서 별도의 구역으로 관리된다.
  • 이 Constant Pool에는 컴파일 타임에 이미 알려진 상수들이 저장되며, 실행 시에는 해당 상수들을 참조한다.
String str1 = "Hello"; // String Pool에 등록
String str2 = "Hello"; // 이미 등록된 문자열이므로 동일한 참조 반환

String str3 = new String("Hello"); // 새로운 String 객체 생성, 힙에 저장
String str4 = str3.intern(); // String Pool에 등록하고 참조 반환

// str1, str2, str3, str4는 모두 같은 문자열을 참조

 

String은 힙 내에서 일반적인 객체처럼 동작하면서, 동시에 String Pool을 활용하여 중복 문자열을 관리한다.