-
Notifications
You must be signed in to change notification settings - Fork 0
Description
박싱된 기본 타입보다는 기본 타입을 사용하라
자바의 데이터 타입은 크게 두 가지로 나뉜다.
- 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, 크면 양수를 반환한다.
하지만 여기에는 심각한 결함이 있다.
다음을 보면 두 인스턴스의 값이 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("믿을 수 없군!");
}
}
위 코드는 "믿을 수 없군!"을 출력하지 않지만 다음과 같은 결과를 보여준다.
원인은 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);
이처럼 박싱과 언박싱이 반복해서 일어나 체감될 정도로 성능이 느려진다. 이는 기본 타입과 박싱된 기본 타입의 차이를 무시한 대가를 치르는 것이다.
박싱된 기본 타입의 사용 시점
박싱된 기본 타입
- 컬렉션의 원소, 키, 값으로 사용 ( 컬렉션은 기본 타입을 담을 수 없음 )
- 매개변수화 타입이나 매개변수화 메서드의 타입 매개변수로는 박싱된 기본타입을 사용하라
정리
- 기본 타입과 박싱된 기본 타입을 선택해야 한다면 기본 타입을 사용하라.
- 오토박싱, 언박싱은 성능저하로 이어진다.
- 박싱된 기본 타입을 == 연산자로 비교하면 의도하지 않은 결과가 야기된다.