Skip to content

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

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

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

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

박싱된 기본 타입

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

정리

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions