Skip to content

[아이템 61] 박싱된 기본 타입보다는 기본 타입을 사용하라 #38

@DongLee99

Description

@DongLee99

박싱된 기본 타입보다는 기본 타입을 사용하라

자바의 데이터 타입은 크게 두 가지로 나뉜다.

  • int, double, boolean 같은 기본 타입
  • String, Double, Long 같은 참조 타입

각 기본 타입에 대응하는 참조 타입이 하나씩 존재하며 이를 박싱된 기본 타입이라고 한다.

  • int -> Integer
  • double -> Double
  • boolean -> Boolean

오토 박싱과 오토 언박싱

#24 에서 자바는 오토박싱과 오토언박싱을 지원하기 때문에 두 타입을 크게 구분하지 않고 사용이 가능하지만 두 타입은 차이가 있다.

  • 기본 타입은 값만 가지고 있고, 박싱된 기본 타입은 식별자와 값을 지니고 있다. (두 인스턴스의 값이 같아도 다르다고 식별될 수 있음)
  • 기본 타입의 값은 언제나 유효하나, 박싱된 기본 타입의 값은 그렇지 않다.(Nullable 하다.)
  • 기본 타입이 박싱된 기본 타입보다 시간과 메모리 사용면에서 더 효율적이다.

첫 번째 차이점 예시 (기본 타입은 값만 가지고 있고, 박싱된 기본 타입은 식별자와 값을 지니고 있다.)

Comparator<Integer> naturalOrder = (i, j) -> (i < j) ? -1 : (i == j ? 0 : 1);

Integer 값을 오름차순으로 정렬하는 비교자 compare 메서드는 첫 번째 원소가 두 번째 원소보다 작으면 음수, 같으면 0, 크면 양수를 반환한다.
하지만 여기에는 심각한 결함이 있다.

image

다음을 보면 두 인스턴스의 값이 1로 같지만 -1을 반환한다. 이는 첫 번째 (i < j)는 잘 작동하지만 두 번째 (i == j) 가 식별자 값으로 비교되어 다음과 같은 결과가 나오는 것이다. 즉 박싱된 기본 타입에 == 연산자를 사용하면 오류가 일어난다.

실무에서 기본 타입을 다루는 비교자가 필요하다면 Comparator.naturalOrder()를 사용하도록 하자.

두 번째 차이점 예시 (기본 타입의 값은 언제나 유효하나, 박싱된 기본 타입의 값은 그렇지 않다.)

public class Unbelievable {
    static Integer i;
    public static void main(String[] args) {
        if (i == 42)
            System.out.println("믿을 수 없군!");
    }
}

위 코드는 "믿을 수 없군!"을 출력하지 않지만 다음과 같은 결과를 보여준다.

image

원인은 i가 int가 아닌 Integer 이며, 다른 참조 타입 필드와 마찬가지로 초기값이 Null이기 때문이다.
즉 i == 42는 Integer와 int를 비교하는 것이다. 기본 타입과 박싱된 기본 타입을 혼용한 연산에는 박싱된 기본 타입의 박싱이 자동으로 풀린다. Null을 언박싱하면 NullPointerException이 발생한다.

세 번째 차이점 예시 (기본 타입이 박싱된 기본 타입보다 시간과 메모리 사용면에서 더 효율적이다.)

// 오토 언박싱 예시
public static void main(String[] args) {
    Long sum = 0L;
    for (long i = 0; i <= Integer.MAX_VALUE; i++) {
        sum += i;
    }
    System.out.println(sum);
}

// 기본 타입
   long sum = 0L;
   for (long i = 0; i <= Integer.MAX_VALUE; i++) {
        sum += i;
   }
   System.out.println(sum);
image

이처럼 박싱과 언박싱이 반복해서 일어나 체감될 정도로 성능이 느려진다. 이는 기본 타입과 박싱된 기본 타입의 차이를 무시한 대가를 치르는 것이다.

박싱된 기본 타입의 사용 시점

박싱된 기본 타입

  • 컬렉션의 원소, 키, 값으로 사용 ( 컬렉션은 기본 타입을 담을 수 없음 )
  • 매개변수화 타입이나 매개변수화 메서드의 타입 매개변수로는 박싱된 기본타입을 사용하라

정리

  • 기본 타입과 박싱된 기본 타입을 선택해야 한다면 기본 타입을 사용하라.
  • 오토박싱, 언박싱은 성능저하로 이어진다.
  • 박싱된 기본 타입을 == 연산자로 비교하면 의도하지 않은 결과가 야기된다.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions