[EffectiveJava] item 61. 박싱된 기본 타입보다는 기본 타입을 사용하라

2025. 7. 1. 20:36·Backend/Java

자바의 데이터 타입은 크게 두 가지로 나눌 수 있다

1. 기본 타입 (원시 타입, Primitive type)

  • int, double, boolean …

2. 참조 타입 (Reference type)

  • String, List, enum, class, interface …

각각의 기본 타입에 대응하는 참조 타입이 하나씩 존재

  • 이를 박싱된 기본 타입(Wrapper Class) 이라고 한다

 

기본 타입과 박싱된 기본 타입의 차이

  1. 기본 타입은 값만 가지고 있으나, 박싱된 기본 타입은 값에 대해 식별성이라는 속성을 가진다.
    • 박싱된 기본 타입의 두 인스턴스는 값이 같아도 다르다고 식별될 수 있다.
  2. 기본 타입의 값은 언제나 유효하나, 박싱된 기본 타입은 null 값을 가질 수 있다.
  3. 기본 타입이 박싱된 기본 타입보다 시간과 메모리 사용에 있어 효율적이다.

오토박싱과 오토언박싱 때문에 두 타입이 자동으로 형변환 되고,
크게 구분해서 사용하지 않을 수 있지만 둘은 큰 차이가 존재하니 주의해서 사용해야 한다.

타입 혼용 예시 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 을 반환

  1. 첫 번째 i < j 에서 Integer 인스턴스는 auto unboxing되어 기본 타입을 변환되고 값을 비교한다
  2. 두 번째 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 을 박싱된 기본 타입으로 선언하여 매우 느린 성능을 보여준다.

  • 오류나 경고 없이 컴파일되지만, 박싱과 언박싱이 반복해서 일어나고 있기 때문

박싱된 기본 타입의 용도

그렇다면 박싱된 기본 타입은 언제 써야할까?

  1. 컬렉션의 원소, 키, 값으로 사용한다.
  2. 매개변수화 타입이나 매개변수화 메서드의 타입 매개변수에 사용한다.
  3. 자바 언어는 타입 매개변수로 기본 타입을 지원하지 않는다.
  4. 리플렉션을 통해 메서드를 호출할 때 사용한다. (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
'Backend/Java' 카테고리의 다른 글
  • [EffectiveJava] Item 14. Comparable을 구현할지 고려하라
  • [EffectiveJava] Item 55. 옵셔널 반환은 신중히 하라
  • [EffectiveJava] item 64. 객체는 클래스가 아닌 인터페이스로 참조하라
  • [EffectiveJava] Item 7. 다 쓴 객체 참조를 해제하라
devoks
devoks
꾸준히 작성해보자!
  • devoks
    ok's 개발 블로그
    devoks
  • 전체
    오늘
    어제
    • 분류 전체보기 (110) N
      • Backend (15)
        • SpringBoot (0)
        • Java (15)
      • Cs (17) N
      • Infra (0)
        • AWS (0)
        • Docker (0)
      • CodingTest (78)
        • Programmers (78)
  • 링크

    • My GitHub
  • 인기 글

  • 태그

    java
    json
    BufferedWriter
    StringTokenizer
    effectivejava
    programmers
    switch
    CS
    codingtest
    BufferedReader
  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
devoks
[EffectiveJava] item 61. 박싱된 기본 타입보다는 기본 타입을 사용하라
상단으로

티스토리툴바