본문 바로가기
Back-end

Primitive Type vs Wrapper Class + Wrapper Class 동일성 비교

by 신재권 2023. 8. 16.

Primitive Type

Primitive Type은 정수, 실수, 문자, 논리 등의 실제 데이터 값을 저장하는 타입입니다.

실제 값을 저장하므로, stack 메모리에 저장됩니다.

또한, 비객체 타입이기 때문에 null 값을 가질 수 없습니다.

스택 메모리에 저장되는 이유는 메모리 관리의 효율성 때문입니다.

primitive type은 기본 데이터 타입으로 크기가 고정되어 있으므로, 해당 크기만큼의 공간을 할당하고, 해당 공간에 직접 값을 저장하는 것이 간단하고 효율적입니다.

Wrapper Class

기본 자료 타입(Primitive)을 객체로 다루기 위해서 사용하는 클래스들을 래퍼 클래스라고 합니다.

즉, 객체로 래핑하며, 객체 지향적인 기능을 활용할 수 있도록 합니다.

왠만하면 primtive type을 쓰는 경우가 좋지만, 사용 못하는 경우도 있습니다.

주로 컬렉션에 사용하지 못하기 때문입니다.

박싱, 언박싱

박싱과 언박싱은 자바 기본 데이터 타입과 래퍼 클래스 간의 변환을 의미합니다.

이를 통해 기본 데이터 타입과 래퍼 클래스 사이에서 필요한 변환작업을 더 편리하게 처리할 수 있습니다.

박싱은 기본 데이터 타입을 래퍼 클래스 객체로 변환하는 것이고, 언박싱은 래퍼 클래스에 저장된 값을 기본 데이터 타입으로 변환하는 과정을 말합니다.

자바에서는 JDK 1.5 부터 자동으로 박싱, 언박싱을 컴파일러가 처리해줍니다.

값 비교

  • 래퍼클래스 == 기본형
  • 래퍼클래스.equals(기본형)
  • 래퍼클래스 == 래퍼클래스 → 특수상황 만 가능
  • 래퍼클래스.equals(래퍼클래스)

래퍼 클래스 == 래퍼 클래스

Integer a = 24;
Integer b = 24;
System.out.println(a == b);

Integer c = 200;
Integer d = 200;
System.out.println(c == d);

위의 두개의 print 문은 무슨 결과가 나올까?

정답은 ture, false가 나온다.

왜 같은 방식으로 값을 할당했는데 다른 결과가 나올까?

 

맨 처음엔 이렇게 알고 있었다.

Wrapper 클래스를 리터럴로 초기화 하면 힙 영역에 상수 풀에 저장된다.

즉, String 클래스와 동일하게 불변성을 가지고, 재활용을 하여 메모리를 아낀다.

하지만 실제로 이 방식으로 동작하지 않았다.

 

Integer의 내부 클래스인 IntegerCache에 의해 왜 그런지 알 수 있다.

Wrapper 클래스에 리터럴로 값을 할당할 때 캐싱 범위에 들어온다면, 캐싱된 값을 반환한다.

범위를 넘어가는 값을 저장하면 우리는 실제 값을 할당하는 것을 기대하지만, 실제로 new Integer()을 통해 값이 할당된다.

 

 

즉, 범위의 값을 미리 Integer 배열에 할당해, 만약 범위안에 값으로 초기화한다고 하면, 해당 Integer 배열의 레퍼런스를 반환한다.

결론적으로 위 범위를 넘어가면 new Integer()로 할당이 되며, 힙 영역에 실제 값이 저장되게 된다.

내부적으로 static Integer[] 으로 선언되어 있다.

 

위 캐시방식은 Boolean, Float, Double 형을 제외한 Wrapper 클래스들에 캐시가 적용되어 있고, Character 클래스는 음수 값을 제외한 양수만이 캐싱되어 있다.

 

결론적으로 Integer에 리터럴로 값을 할당하면, 일정 범위는 상수 풀이 아닌 이미 배열에 캐싱된 값을 참조하게 되고, 범위가 넘어가면 내부적으로 new Integer() 를 통해 힙에 객체를 할당하게 된다.


실제 위 내용을 증명한 블로그가 있어 출처를 남긴다.

실험을 보면 범위가 넘어가면 new Integer()을 사용하기 때문에 Heap OOM 에러가 발생한다. 범위를 넘어가지않으면 무한히 터지지 않는다.

https://velog.io/@lee_choonghee/Java-IntegerCache를-만나봤니

'Back-end' 카테고리의 다른 글

hashCode()  (0) 2023.08.16
왜 float과 double은 == 연산을 사용하면 안될까?  (0) 2023.08.16
동일성 vs 동등성  (0) 2023.08.16
static vs static final vs final In Java  (0) 2023.08.15
2023.08.13 TIL  (0) 2023.08.13