자바의 데이터 타입은 크게 두 가지로 나눌 수 있다
1. 기본 타입 (원시 타입, Primitive type)
- int, double, boolean …
2. 참조 타입 (Reference type)
- String, List, enum, class, interface …
각각의 기본 타입에 대응하는 참조 타입이 하나씩 존재
- 이를 박싱된 기본 타입(Wrapper Class) 이라고 한다
기본 타입과 박싱된 기본 타입의 차이
- 기본 타입은 값만 가지고 있으나, 박싱된 기본 타입은 값에 대해 식별성이라는 속성을 가진다.
- 박싱된 기본 타입의 두 인스턴스는 값이 같아도 다르다고 식별될 수 있다.
- 기본 타입의 값은 언제나 유효하나, 박싱된 기본 타입은
null
값을 가질 수 있다. - 기본 타입이 박싱된 기본 타입보다 시간과 메모리 사용에 있어 효율적이다.
타입 혼용 예시 1️⃣
잘못 구현된 비교자
public class Main {
public static void main(String[] args) {
Comparator<Integer> naturalOrder = (i, j) -> (i < j) ? -1 : (i == j ? 0 : 1);
int compare = naturalOrder.compare(new Integer(42), new Integer(42));
System.out.println("compare = " + compare); // compare = 1
}
}
두 Integer
객체를 비교했을 때, 숫자의 값이 같아서 0
을 반환해야 할텐데 1
을 반환
- 첫 번째
i < j
에서 Integer 인스턴스는 auto unboxing되어 기본 타입을 변환되고 값을 비교한다 - 두 번째
i == j
에서는 '객체 참조'의 식별성을 검사하게 된다.- 내용 기준이 아닌 객체의 주소값을 기준으로 비교하게 되고,
서로 다른 Integer 인스턴스라면 1을 반환하게 되는 것이다.
- 내용 기준이 아닌 객체의 주소값을 기준으로 비교하게 되고,
해결
Comparator<Ineteger> naturalOrder = (iBoxed, jBoxed) -> {
int i = iBoxed, j = jBoxed; // 오토 언박싱
return i < j ? -1 : (i == j ? 0 : 1);
타입 혼용 예시2️⃣
public class Unbelievable {
static Integer i; // 예외 발생!
public static void main(String[] args){
if (i == 42)
System.out.println("믿을 수 없군!");
}
}
i == 42
를 검사할때 NullPointerException
가 발생하게 됨
- Integer가 다른 참조 타입 필드와 마찬가지로 초기값이
null
이기 때문 - 거의 예외 없이 기본 타입과 박싱된 기본 타입을 혼용한 연산에서는 박싱된 기본 타입의 박싱이 자동으로 풀린다.
- →
null
참조를 언박싱하게 되면NullPointerException
이 발생하는 것
타입 혼용 예시3️⃣
public static void main(String[] args) {
Long sum = 0L;
for (long i = 0; i <= Integer.MAX_VALUE; i++) {
sum += i; // sum = sum + i
}
System.out.println(sum);
}
지역변수 sum
을 박싱된 기본 타입으로 선언하여 매우 느린 성능을 보여준다.
- 오류나 경고 없이 컴파일되지만, 박싱과 언박싱이 반복해서 일어나고 있기 때문
박싱된 기본 타입의 용도
그렇다면 박싱된 기본 타입은 언제 써야할까?
- 컬렉션의 원소, 키, 값으로 사용한다.
- 매개변수화 타입이나 매개변수화 메서드의 타입 매개변수에 사용한다.
- 자바 언어는 타입 매개변수로 기본 타입을 지원하지 않는다.
- 리플렉션을 통해 메서드를 호출할 때 사용한다. (item 65)
📚 정리
기본 타입과 박싱된 기본 타입 중 하나를 선택해야 한다면 가능한 기본 타입을 사용하자.
박싱된 기본 타입을 써야 한다면, 다음의 세가지를 꼭 기억하자.
1) 박싱된 기본 타입을 == 로 비교하면 식별성 검사가 이루어진다.
2) 박싱된 기본 타입에서 기본 타입으로 언박싱하는 과정에서
NullPointerException
이 발생할 수 있다.3) 기본 타입을 박싱하는 작업은 필요 없는 객체를 생성하는 부작용이 있다.
'Backend > Java' 카테고리의 다른 글
[Java] 정렬 알고리즘 정리 (1) | 2025.07.02 |
---|---|
[EffectiveJava] Item 14. Comparable을 구현할지 고려하라 (1) | 2025.07.01 |
[EffectiveJava] Item 55. 옵셔널 반환은 신중히 하라 (1) | 2025.07.01 |
[EffectiveJava] item 64. 객체는 클래스가 아닌 인터페이스로 참조하라 (0) | 2025.07.01 |
[EffectiveJava] Item 7. 다 쓴 객체 참조를 해제하라 (0) | 2025.07.01 |