박싱된 기본 타입보다는 기본 타입을 사용하라
자바의 데이터 타입
- 기본타입 - int, double, boolean ...
- 참조타입 - String, List ...
- 박싱된 기본 타입 - Integer, Double, Boolean ...
오토박싱과 오토언박싱 덕분에 두 타입을 크게 구분하지 않고 사용할 수는 있지만 차이는 있다. 어떤 타입을 사용하는지는 상당히 중요하다.
기본타입과 박싱된 기본 타입과의 차이
- 기본 타입은 값만 가지고 있으나, 박싱된 기본 타입은 값에 더해 식별성이란 속성을 갖는다. 즉 두 인스턴스의 값이 같아도 다르다고 식별 될 수 있다.
- 기본 타입의 값은 언제나 유효하나, 박싱된 기본 타입의 값은 null(유효하지 않은 값)을 가질 수 있다.
- 기본 타입이 시간과 메모리 사용면에서 유리하다.
이러한 차이로 주의하지 않고 사용한다면 문제가 발생할 수 있다.
실제 문제
Integer 값을 오름차순으로 정렬하는 비교자다. Integer는 그 자체로 순서가 있으니 이 비교자가 실질적인 의미는 없지만,
흥미로운 점이 하나 있다.
// 잘못 구현된 비교자 - 문제를 찾아보자
Comparator<Integer> naturalOrder = (i, j) -> (i < j) ? -1 : (i == j ? 0 : 1);
눈으로 봐서는 문제를 찾기 힘들지만, naturalOrder.compare(new Integer(100), new Integer(100))의 값을 출력하면, 두 값이 같으므로 0을 출력할 것 같지만,
1을 출력한다.
첫번째 검사는 잘 작동한다(i < j) 여기서 i와 j가 참조하는 오토박싱된 Integer 인스턴스는 기본 타입으로 변환된다.
그런 다음 첫 번째 정수가 두 번째 값보다 작은지를 평가한다. 만약 작지 않으면 두번째 검사(i==j)가 이뤄진다.
그런데 두 번째 검사에서는 '객체 참조'의 식별성을 검사하게 된다. i와 j가 서로 다른 Integer 인스턴스라면(비록 값은 같더라도)
이 비교의 결과는 false가 되고, 비교자는 1을 반환한다. 박싱된 기본 타입에 == 연산자를 사용하면 오류가 일어난다
실무에서 이와 같이 기본 타입을 다루는 비교자가 필요하다면, Comparator.naturalOrder()를 사용하자. 비교자를 직접만들면 비교자 생성 메서드나
기본 타입을 받는 정적 compare 메서드를 사용해야 한다.
// 문제를 수정한 비교자
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("믿기 힘들군!");
}
}
}
i는 Integer이며 초기화를 안해주었으므로 초기값은 null이다(참조 타입이기 때문) 0이 아니다.
그러므로 위의 결과는 NullPointerException이 발생한다. 주의해야 한다.
박싱된 기본 타입의 쓰임
언제써야 할까?
- 컬렉션의 원소, 키, 값으로 쓴다. - 기본 타입을 담을 수 없으므로 박싱된 기본 타입을 써야한다. 매개변수화 타입이나 매개변수화 메서드의 타입 매개변수로는 박싱된 기본 타입을 써야한다.
- 리플렉션을 통해 메서드를 호출할 때도 박싱된 기본 타입을 사용해야 한다.
출처:effective java item61
'Java' 카테고리의 다른 글
메서드 시그니처를 신중히 설계하라. (0) | 2021.02.09 |
---|---|
문자열 연결을 고민한다면 String 보다는 StringBuilder (0) | 2021.02.08 |
정확한 계산이 필요할 땐 float와 double은 피하자 (0) | 2021.01.18 |
지역변수의 범위는 최소화하자 (0) | 2021.01.05 |
Optional 반환은 신중히하자 (0) | 2020.12.31 |