자바의 데이터 타입은 크게 두 가지로 나눌 수 있다. 바로 기본 타입과 참조 타입이다. 그리고 각각의 기본 타입에 대응하는 참조 타입이 하나씩 있고 이를 박싱된 기본 타입이라고 한다. 예를 들어 int
,double
,boolean
에 대응하는 박싱된 기본 타입은 Integer
,Double
,Boolean
이다.
기본 타입과 박싱된 기본 타입의 주된 차이는 크게 세 가지다.
이상의 세 가지 차이점을 주의하지 않고 사용하면 문제가 발생할 수 있다.
Comparator<Integer> naturalOrder = (i, j) -> (i < j) ? -1 : (i == j ? 0 : 1);
다음 코드는 문제가 있다. 박싱된 기본 타입을 == 연산자로 비교를 하면 식별성을 검사하게 되고, 이는 같은 값을 가진 인스턴스라도 0이 나오는 경우는 없다.
Comparator<Integer> naturalOrder = (iBoxed, jBoxed) -> {
int i = iBoxed, j = jBoxed;
return i < j ? -1 : (i == j ? 0 : 1);
};
위 코드에서 오토박싱은 성능저하를 수반한다는 점을 기억하자. 그리고 다음코드를 보자.
public class Unbelievable {
static Integer i;
public static void main(String[] args) {
if(i == 42)
System.out.println("Unbelievable");
}
}
위 코드는 NPE를 던진다. i == 42 는 Integer
과 int
를 비교하는 것이다. 기본 타입과 박싱된 기본 타입을 혼용한 연산에서는 기본 타입의 박싱이 자동으로 풀린다. 그리고 null 참조를 언박싱하게되면 NPE가 발생하는 것이다.
Long sum = 0L;
for(long i = 0; i <= Integer.MAX_VALUE; i++) {
sum += i;
}
System.out.println(sum);
다음 코드는 심각한 성능 저하를 유발한다. sum을 Long
으로 선언했기 때문에 반복문을 돌 때마다 언박싱을 해야 하기 때문이다.