Java시작과 문법

래퍼 클래스와 오토박싱

기본 타입이 컬렉션에 들어갈 수 없는 이유, 오토박싱이 자동으로 일어나는 시점, 예상치 못한 `NullPointerException`과 `==` 비교 함정을 정리합니다.

마지막 수정 2026년 3월 27일

기본 패턴

java
// 기본 타입 ↔ 래퍼 클래스
int primitive = 42;
Integer boxed = primitive;      // 오토박싱 — 컴파일러가 Integer.valueOf(42)로 변환
int unboxed = boxed;            // 언박싱 — 컴파일러가 boxed.intValue()로 변환

// 컬렉션에는 래퍼 클래스 필요
List<Integer> numbers = new ArrayList<>();
numbers.add(10);   // 오토박싱
int n = numbers.get(0); // 언박싱

설명

기본 타입과 래퍼 클래스가 공존하는 이유

Java의 기본 타입(int, double, boolean 등)은 객체가 아닙니다. 값만 담는 가볍고 빠른 저장 단위입니다. 반면 컬렉션(List<T>, Map<K, V>)은 제네릭의 타입 매개변수 자리에 객체만 올 수 있습니다.

이 간극을 메우기 위해 각 기본 타입에 대응하는 래퍼 클래스가 존재합니다: intInteger, doubleDouble, booleanBoolean 등. 오토박싱은 컴파일러가 intInteger로(박싱), Integerint로(언박싱) 자동 변환하는 기능입니다.

java
// 기본 타입 — 객체 아님, 컬렉션 불가
int x = 10;
// List<int> list = ...; // 컴파일 오류

// 래퍼 클래스 — 객체, 컬렉션 가능
List<Integer> list = new ArrayList<>();
list.add(10); // 오토박싱: int 10 → Integer 10

오토박싱의 비용과 Integer 캐시

오토박싱은 편리하지만 힙 할당이 일어납니다. 루프 안에서 반복적으로 박싱/언박싱이 일어나면 불필요한 객체가 대량 생성됩니다.

한 가지 중요한 세부사항: Java는 -128 ~ 127 범위의 Integer 객체를 캐시합니다. 이 범위 안에서는 ==로 비교해도 true가 나오지만, 범위 밖에서는 다른 객체가 생성되어 ==false가 됩니다. Integer 값 비교는 항상 equals()를 써야 합니다.

java
// ⚠ Integer 캐시 범위 내 — == 가 true
Integer a = 100;
Integer b = 100;
System.out.println(a == b); // true (캐시된 같은 객체)

// ⚠ Integer 캐시 범위 밖 — == 가 false
Integer c = 200;
Integer d = 200;
System.out.println(c == d);      // false (다른 객체)
System.out.println(c.equals(d)); // true (값 비교)

언박싱과 NullPointerException

Integer 같은 래퍼 클래스는 null을 가질 수 있습니다. null인 래퍼를 기본 타입에 대입하면 언박싱이 일어나고 NullPointerException이 발생합니다. 특히 메서드 반환값이나 Map에서 가져온 값을 기본 타입 변수에 바로 대입할 때 주의해야 합니다.

java
Map<String, Integer> scores = new HashMap<>();
// "Alice"는 map에 없음

// ❌ 없는 키 → null 반환 → int 언박싱 → NullPointerException
int score = scores.get("Alice"); // NullPointerException

// ✅ getOrDefault로 기본값 지정
int score = scores.getOrDefault("Alice", 0); // 0

// ✅ 또는 null 체크 후 언박싱
Integer value = scores.get("Alice");
if (value != null) {
    int s = value; // 안전한 언박싱
}

빠른 정리

상황선택
기본 타입 컬렉션 저장래퍼 클래스 (Integer, Double 등)
성능 민감한 수치 연산기본 타입 (int, double)
래퍼 값 비교equals() (== 금지)
Map에서 가져온 값 언박싱getOrDefault() 또는 null 체크 후
유틸리티 메서드Integer.parseInt(), Integer.max()

주의할 점

null인 래퍼 타입을 기본 타입 변수에 대입하면 언박싱 시 NullPointerException이 발생합니다. 반환 타입이 래퍼 클래스인 메서드는 항상 null 가능성을 고려하세요.

java
Integer getCount() {
    return null; // null 반환 가능
}

// ❌ 직접 언박싱 — NullPointerException
int count = getCount();

// ✅ null 체크 후 언박싱
Integer raw = getCount();
int count = (raw != null) ? raw : 0;

// ✅ Optional 활용
int count = Optional.ofNullable(getCount()).orElse(0);

참고 링크

1 sources