[Effective Java] 박싱된 기본 타입보다는 기본 타입을 사용하라

들어가며

자바의 기본타입에는 이에 따라오는 박싱된 기본타입이 있다. Integer, Double, Boolean이 그 예다. 이런 기본 타입과 박싱된 기본 타입의 주된 차이는 다음과 같다.

첫째로 기본 타입은 값만 가지고 있고 박싱된 타입은 값과 식별성을 가진다. 그렇기 때문에 같은 값을 가진 두 박싱된 기본 타입의 인스턴스는 서로 다르다고 식별될 수 있다. 둘째로 기본 타입의 값은 언제나 유효하나 박싱된 기본 타입은 유효하지 않은 값인 null을 가질 수 있다. 세번째로 기본 타입이 박싱된 기본 타입보다 시간과 메모리 사용면에서 더 효율적이다. 다음 코드를 보자.

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

다음 코드는 문제가 생긴다. 박싱된 기본 타입을 ==비교를 하니 식별성을 검사하게 되고 이는 같은 값을 가진 인스턴스라도 0이 나오는 경우는 없다. 이럴때는 오토 언방식을 해야한다.

1
2
3
4
Comparator<Integer> naturalOrder = (iBoxed, jBoxed) -> {
int i = iBoxed, j = jBoxed;
return i < j ? -1 : (i == j ? 0 : 1);
};

위 코드에서 오토박싱은 성능저하를 수반한다는 점을 기억하자. 그리고 다음코드를 보자.

1
2
3
4
5
6
7
8
public class Unbelievable {
static Integer i;

public static void main(String[] args) {
if(i == 42)
System.out.println("Unbelievable");
}
}

위 코드는 NullPointerException을 던진다. 박싱된 기본 타입과 기본타입에 비교에선 언방싱이 수행되는데 이 때 유효하지 않은 값으로 인해 에러가 나오는 것이다. 그리고 다음 코드를 보자.

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

다음 코드는 심각한 성능저하를 유발한다. 그럼 박싱된 기본 타입은 언제 써야할까? 첫째로 컬렉션의 원소, 키, 값으로 사용한다. 둘째로 리플렉션을 통해 메소드를 호출할 때도 박싱된 기본 타입을 사용해야 한다.

Author: Song Hayoung
Link: https://songhayoung.github.io/2020/08/19/Languages/Effective%20JAVA/item61/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.