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

기본타입과 박싱된 기본타입의 주된 차이는 크게 세가지다.

  • 박싱된 기본 타입은 값 + 식별성이란 속성을 갖는다.
    • 박싱된 기본 타입의 두 인스턴스는 값이 같아도 서로 다르다고 식별될 수 있다.
  • 박싱된 기본 타입은 null을 가질 수 있다.
  • 기본타입이 박싱된 기본타입보다 시간과 메모리 사용면에서 더 효율적이다.

다음은 Integer 값을 오름차순으로 정렬하는 비교자다.

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

잘 동작하는 것처럼 보이지만, Integer(42) 를 비교하면 놀랍게도 0이 아닌 1을 리턴한다.

System.out.println(naturalOrder.compare(new Integer(42), new Integer(42)));

== 연산에서 값의 비교가 아닌, 두 객체 참조의 식별성을 검사한 것이다. 이처럼 박싱된 기본 타입에 == 연산자를 사용하면 오류가 일어난다. 따라서 Comparator.naturalOrder()를 사용하자!

기본 타입과 박싱된 기본 타입을 혼용한 연산에서는 박싱된 기본 타입의 박싱이 자동으로 풀린다. 따라서 아래 코드는 NullPointerException 을 던진다.

static Integer i;

public static void main(String[] args) {

  if(i == 42) { // NullPointerException
    System.out.println("Unbelivable");
  }

}

박싱된 기본타입을 선언하고, 박싱과 언박싱을 반복해서 수행하면 속도가 느려진다

Long sum = 0L;
for(long i=0; i<= Integer.MAX_VALUE; i++) {
  sum += i;
}
System.out.println(sum);

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

  1. 컬렉션의 원소, 키, 값으로 쓴다. 컬렉션은 기본 타입을 담을 수 없으므로 어쩔 수 없이 박싱된 기본 타입을 써야만 한다.
  2. 리플렉션을 통해 메서드를 호출할 때도 박싱된 기본 타입을 사용해야 한다.

댓글남기기