Search

Item 61. 박싱된 기본 타입보다는 기본 타입을 사용하라

생성일
2023/08/08 00:15
챕터
9장 - 일반적인 프로그래밍 원칙

요약

박싱된 기본 타입을 사용할 때는 == 연산자를 주의해서 사용하자.
박싱된 기본 타입을 사용할 때는 항상 null이 들어있을 수 있음을 인지하자.
박싱된 기본 타입은 오토 박싱과 오토 언박싱으로 기본 타입보다 성능이 떨어진다.
제네릭과 제네릭 메서드의 매개변수 타입에는 박싱된 타입만 사용 가능하다.

기본 타입과 박싱된 기본 타입

자바에는 기본 타입과 기본 타입에 대응하는 박싱된 기본 타입이 있다. 예를 들면, int, double, boolean에 대응되는 Integer, Double, Boolean 타입이 있다.
오토 박싱과 오토 언박싱으로 인해 두 타입을 크게 구분하지 않고 사용할 수 있지만, 기본 타입과 박싱된 기본 타입의 차이를 이해하고 잘 선택해서 사용해야 한다.
기본 타입과 박싱된 기본타입의 차이는 크게 세 가지가 있다.
1.
기본 타입은 값만 가지고 있지만, 박싱된 기본 타입은 식별성(identity)을 가진다.
Comparator<Integer> naturalOrder = (i, j) -> (i < j) ? -1 : (i == j ? 0 : 1);
Java
복사
위 코드는 거의 문제가 없지만, naturalOrder.compare(new Integer(42), new Integer(42))를 사용하는 경우에 1이 나온다.
그 이유는 오토 박싱된 Integer 인스턴스로 검사를 수행하는데, (i == j)에서 두 객체의 값을 비교하는게 아니라 식별성을 검사하여 오류가 발생한 것이다.
이처럼 박싱된 기본 타입은 식별성을 가지기 때문에 == 연산자를 주의해서 사용하자.
위 코드를 실제 동작 시켜보기 위해 코드를 입력하면,
이와 같이 new Integer() 방식이 deprecated 되었다며 오류가 발생한다.
이는 이전 아이템에서
String s1 = "1234"; String s2 = new String("1234");
Java
복사
이와 같이 생성자를 호출하여 사용하는 것이 불필요하고 효율이 좋지 않기 때문에 사용하지 말라는 점을 java에서 deprecate시켜 개선한 것으로 보인다.
2.
기본 타입의 값은 언제나 유효하지만, 박싱된 기본 타입은 null을 포함할 수 있다.
public class Ubelievable { static Integer i; public static void main(String[] args) { if (i == 42) System.out.println("믿을 수 없군!"); } }
Java
복사
위 코드는 Integer i 값이 static 멤버 변수로 선언되어 null로 초기화 되었기 때문에, if 문의 i == 42를 검사할 때 NullPointerException이 발생한다.
또한 기본 타입과 박싱된 기본 타입을 혼용하여 연산하면 박싱된 기본 타입이 오토 언박싱된다. 이 과정에서 박싱된 기본 타입에 null이 들어있다면 NPE가 발생한다.
이와 같이 null을 포함할 수 있기 때문에, 주의해서 사용해야 한다.
3.
기본 타입이 박싱된 기본 타입보다 시간과 메모리 사용 측면에서 더 효율적이다.
기본 타입과 박싱된 기본 타입을 잘못 사용하면, 박싱과 언박싱이 반복해서 일어나 성능이 무척이나 떨어지게 된다.
결과
Long + long : 2563 ms long + Long : 2763 ms Long + Long : 5068 ms long + long : 368 ms
Java
복사
기본 타입과 박싱된 기본 타입을 사용하면 오토 언박싱으로 기본 타입으로 변환하여 연산한다고 책에 언급되어 있다. 위의 예시들은 연산 과정이 들어갔기 때문에 Long + Long과 같은 경우에도 둘 다 언박싱하는 오버헤드로 더 느려진 것 같다. 실제 단순 대입을 반복하는 예제를 만들어 테스트 해봤을 경우,
long + long : 341 ms Long + long : 2506 ms long + Long : 2478 ms Long + Long : 2523 ms
Java
복사
으로 결과가 나왔다.
컬렉션의 원소, key, value로 사용하는 경우처럼, 컬렉션의 제네릭이 기본 타입을 담을 수 없기 때문에 박싱된 기본타입을 사용해야 한다. 이와 같이 매개변수화 타입이나 매개변수화 메서드의 타입 매개변수에는 박싱된 기본 타입을 사용해야한다.