View
자바의 데이터 타입은 크게 int, long, boolean과 같은 기본 타입과 String, List 같은 레퍼런스 타입으로 나눌 수 있다. 각각의 기본 타입에는 대응하는 레퍼런스 타입이 하나씩 존재하고, 이를 박싱 된 기본 타입(Integer, Long, Boolean 등)이라 한다.
오토 박싱과 오토 언박싱 덕분에 두 타입을 크게 구분하지 않고 사용할 수 있지만, 어떤 타입을 선택하고 사용하는지는 상당히 중요하다. 이 둘의 차이점을 명확히 파악하고 사용해야 발생하는 문제들을 최소화할 수 있다.
기본 타입과 박싱된 기본 타입의 차이점
1. 기본 타입은 값만 가지고 있으나, 박싱 된 기본 타입은 식별성도 가지고 있다.
박싱 된 기본 타입의 두 인스턴스는 값이 같아도 서로 다른 인스턴스로 인식될 수 있다.
Comparator<Integer> naturalOrder = (i, j) -> (i < j) ? -1 : (i == j ? 0 : 1);
// 1 출력
System.out.println("박싱된 기본 타입: " +
naturalOrder.compare(new Integer(42), new Integer(42)));
// 0 출력
System.out.println("기본 타입: " +
naturalOrder.compare(42, 42));
위의 예시에서의 오류는 i == j 부분에서 발생한다. 박싱 된 기본 타입은 식별성을 가지므로 == 연산자로 비교할 경우 서로의 레퍼런스를 비교하게 된다. 즉, 같은 값을 가졌다 해도 false가 되기 때문에 1이 반환된다. 이처럼 (같은 객체를 비교하는 게 아니라면) 박싱 된 기본 타입에 == 연산자를 사용하면 오류로 이어질 수 있다.
2. 기본 타입의 값은 언제나 유효하지만, 박싱된 기본 타입은 null을 가질 수 있다.
static Integer i;
public static void main(String[] args) {
if (i == 42) { // NullPointerException 발생!!
Ststem.out.println("unbelievable");
}
}
위의 예시에서는 if 문을 검사할 때 NullPointerException이 발생한다. 그 이유는 박싱 된 기본 타입의 초깃값은 null이라는 것에 있다. i == 42를 비교하면 Integer와 int를 비교하는 형태가 된다. 따라서 박싱 된 기본 타입에 오토 언박싱이 일어나고 이때 초깃값이 null인 참조를 언박싱하면 NullPointerException이 발생한다.
3. 기본 타입이 박싱된 기본 타입보다 시간과 메모리 사용에 효율적이다.
private static long sum(){
Long sum = 0L;
for(long i =0; i <= Integer.MAX_VALUE; i++){
sum += i;
}
return sum;
}
위의 코드에서는 불필요한 인스턴스가 2^31개 만들어진다. 박싱 된 기본 타입인 Long을 명시했기 때문이다.
오류나 경고없이 컴파일되지만, 성능이 크게 느려진다.
기본 타입과 박싱된 기본 타입의 차이를 간과하면 이렇듯 큰 문제를 맞이할 수 있다. 생각지 못한 오류로 이어질 수도, 심각한 성능 문제를 발생시킬 수도 있다.
박싱된 기본 타입은 언제 써야 할까?
1. 컬렉션의 원소, 키, 값으로 사용
컬렉션은 기본 타입을 담을 수 없으므로 박싱 된 기본 타입을 써야 한다. 즉, 매개변수화 타입이나 매개변수화 메서드의 타입 매개변수로는 박싱 된 기본 타입을 써야한다.
2. 리플렉션을 통해 메서드를 호출할 때
핵심 정리
- 기본 타입과 박싱된 기본 타입 중 선택지가 있다면 가능한 기본 타입을 사용하자.
- 박싱된 기본 타입을 사용할 때는 주의를 기울이자.
- 박싱된 기본 타입에 == 연산자를 사용하지 말자.
- 기본 타입과 박싱된 기본 타입을 혼용하면 언박싱이 이뤄지며, 이 과정에서 NullPointerException이 발생할 수 있다.
- 기본 타입을 박싱하는 과정은 불필요한 객체 생성으로 이루어질 수 있으니 주의하자.
'BackEnd > 이펙티브 자바' 카테고리의 다른 글
[이펙티브 자바] Item63 - 문자열 연결은 느리니 주의하라 (0) | 2021.08.16 |
---|---|
[이펙티브 자바] Item62 - 다른 타입이 적절하다면 문자열 사용을 피하라 (0) | 2021.08.08 |
[이펙티브 자바] Item60 - 정확한 답이 필요하다면 float와 double은 피하라 (0) | 2021.08.03 |
[이펙티브 자바] Item59 - 라이브러리를 익히고 사용하라 (0) | 2021.08.01 |
[이펙티브 자바] Item58 - 전통적인 for 문보다는 for-each 문을 사용하라 (0) | 2021.07.30 |