Item 61 : 박싱된 기본 타입보다는 기본 타입을 사용하라
2021. 8. 29. 01:15
- 자바의 데이터 타입은 크게 두가지이다
- int, double, boolean과 같은 기본타입과 String, List 같은 참조타입이다.
- 그리고 각각의 기본 타입에는 대응하는 참조 타입이 하나씩있으며 이를 박싱된 기본타입이라 한다.
- int - Integer, double - Double, boolean - Boolean
기본타입과 박싱된 기본타입의 차이점 세가지
- 기본 타입은 값만 가지고 있으나 박싱된 기본 타입은 값에 더해 식별성(identity)이란 속성을 갖는다.
- 박싱된 기본 타입은 값이 같아도 구별이 가능하다.
- 기본 타입의 값은 언제나 유효하나 박싱된 기본타입은 null을 가질 수 있다.
- 기본 타입이 박싱된 기본타입보다 시간과 메모리 사용면에서 더 효율적이다.
주의사항
//잘못 구현된 비교자
Comparator<Integer> naturalOrder =
(i, j) -> (i < j) ? -1 : (i == j ? 0 : 1);
이것은 Integer값을 오름차순으로 정렬하는 비교자다.
naturalOrder.compare(new Integer(42), new Integer(42))의 값을 출력한다면
42와 42를 비교하는 것이기 때문에 우리는 결과값 0을 기대하지만 실제로는 1을 출력한다.
그 이유는 == 연산자가 Integer의 value를 확인하는 것이 아닌 같은 객체인지를 확인하기 때문이다.
이렇듯 박싱된 기본 타입에 == 연산자를 사용하면 오류가 일어난다.
이 문제를 고치려면 지역변수 2개를 두어 각각 박싱된 Integer에 매개변수의 값을 기본 타입 정수로 저장한 다음 모든 비교를 이 기본 타입 변수로 수행해야 한다.
//문제를 수정한 비교자
Comparator<Integer> naturalOrder = (iBoxed, jBoxed) -> {
int i = iBoxed, int j = jBoxed;//오토박싱
return (i < j) ? -1 : (i == j ? 0 : 1);
};
또 다른 문제
//박싱 타입은 초깃값이 null이다.
public class Unbelievable {
static Integer i;
public static void main(String[] args) {
if (i == 42) {
System.out.println("믿을 수 없군");
}
}
}
- 기본 타입과 박싱된 기본타입을 혼용한 연산에서는 박싱된 기본 타입이 박싱이 자동으로 풀린다.
- 그리고 null 참조를 언박싱하면 NullPointerException이 발생한다.
- i를 int로 선언하면 문제 없다.
//성능 저하 문제
public static void main(String[] args) {
Long sum = 0L;
for (long i = 0; i <= Integer.MAX_VALUE; i++) {
sum += i;
}
}
- sum은 Long이지만 i는 long이기 때문에 연산시에 박싱-언박싱이 계속 반복된다.
- 불필요한 Long객체가 계속해서 생성되어 메모리도 낭비된다.
박싱된 기본 타입 사용하는 경우
- 컬렉션의 원소, 키, 값으로 사용
- 컬렉션은 기본타입을 담을 수 없기 때문
- 리플렉션을 통해 메소드를 호출할 때
- ITEM 65에서 정리 예정
정리
- 기본타입과 박싱된 기본타입 중에서 가는하면 기본타입을 사용하자
- 오토박싱과 언박싱을 유의할 것
'책 > 이펙티브자바' 카테고리의 다른 글
Item 63 : 문자열 연결은 느리니 주의하라 (0) | 2021.08.30 |
---|---|
Item 62 : 다른 타입이 적절하다면 문자열 사용을 피하라 (0) | 2021.08.29 |
Item 60 : 정확한 답이 필요하다면 float와 double은 피하라 (0) | 2021.08.27 |
Item 58 : 전통적인 for 문보다는 for-each 문을 사용하라 (0) | 2021.08.26 |
Item 57 : 지역변수의 범위를 최소화하라 (0) | 2021.08.25 |