- 기본타입 :
int
,double
,long
,boolean
등등 - 참조 타입 :
String
,List
등등- 박싱된 기본 타입 : 각각 기본 타입에 대응하는 참조타입 (
Integer
,Long
,Boolean
)
- 박싱된 기본 타입 : 각각 기본 타입에 대응하는 참조타입 (
즉, 박싱된 기본 타입의 두 인스턴스의 값이 같아도 서로 다르다고 식별될 수 있다.
Comparator<Integer> naturalOrder = (i, j) -> (i < j) ? -1 : (i == j ? 0 : 1);
System.out.println(naturalOrder.compare(new Integer(42), new Integer(42))); // 1
i == j
에서 객체 참조의 식별성을 검사하게 된다. 그래서 비교 결과가 false로 나오고, 비교자는 1을 반환하는 것이다.
같은 객체를 비교하는게 아니라면 박싱된 기본 타입에 ==
연산자를 사용하면 오류가 발생한다.
Comparator<Integer> naturalOrder = (iBoxed, jBoxed) -> {
int i = iBoxed;
int j = jBoxed;
return (i < j) ? -1 : (i == j ? 0 : 1);
};
기본 타입으로 값을 저장한 다음 비교하면, 식별성 검사가 이루어지지 않아 정상적인 값이 나온다.
Integer i;
if(i == 42) { // NullPointerException
System.out.println("당첨");
}
여기서 i는 int
가 아닌 Integer
로 다른 참조 타입과 마찬자기로 초기값이 null
이기 때문에 발생하는 오류이다.
기본 타입과 박싱된 기본 타입을 혼용한 연산에서는 박싱된 기본 타입의 박싱이 자동으로 풀리며, null
을 참조하는 값을 언박싱하면 NullPointerException
이 발생하는 것이다.
int i; // 0
if(i == 42) {
System.out.println("당첨");
}
Long sum = 0L;
for (long i = 0; i <= Integer.MAX_VALUE; i++){
sum += 1;
}
지역변수 sum을 박싱된 기본타입으로 선언하여 느려진 코드이다. 오류나 경고 없이 컴파일 되지만, 박싱과 언박싱이 반복해서 일어나 체감될 정도로 성능이 느려진다.
이러한 3가지 차이점 때문에 항상 주의하고 사용해야한다.
-
컬렉션의 원소, 키, 값으로 사용 : 컬렉션은 기본타입을 담을 수 없어 박싱된 기본타입을 사용해야한다.
-
매개변수화 타입이나 매개변수화 메서드의 타입 매개변수로 사용 : 자바 언어가 타입 매개변수로 기본 타입을 지원하지 않음
-
리플렉션을 통해 메서드를 호출할 때 사용
기본 타입은 간단하고 빠르므로, 가능하다면 기본타입을 사용하는 것이 좋다. 오토 박싱은 박싱된 기본 타입을 사용할 때 번거러움을 줄여주지만, 리스크까지 없애주지 않는다.