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

신명철·2022년 3월 23일
0

Effective Java

목록 보기
58/80

들어가며

자바의 데이터 타입은 크게 두 가지로 나눌 수 있다. 바로 기본 타입과 참조 타입이다. 그리고 각각의 기본 타입에 대응하는 참조 타입이 하나씩 있고 이를 박싱된 기본 타입이라고 한다. 예를 들어 int,double,boolean에 대응하는 박싱된 기본 타입은 Integer,Double,Boolean이다.

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

차이점

기본 타입과 박싱된 기본 타입의 주된 차이는 크게 세 가지다.

  • 첫 번째, 기본 타입은 값만 가지고 있으나, 박싱된 기본 타입은 값에 더해 식별셩을 갖는다. 달리 말해 박싱된 기본 타입의 두 인스턴스는 값이 같아도 서로 다르다고 식별될 수 있다.
  • 두 번째, 기본 타입의 값은 언제나 유효하나, 박싱된 기본 타입은 유효하지 않은 값 null을 가질 수 있다.
  • 세 번째, 기본 타입이 박싱된 기본 타입보다 시간과 메모리 사용면에서 더 효율적이다.

이상의 세 가지 차이점을 주의하지 않고 사용하면 문제가 발생할 수 있다.

기본타입과 박싱된 기본타입의 비교 연산자

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

다음 코드는 문제가 있다. 박싱된 기본 타입을 == 연산자로 비교를 하면 식별성을 검사하게 되고, 이는 같은 값을 가진 인스턴스라도 0이 나오는 경우는 없다.

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("Unbelievable");
	}
}

위 코드는 NPE를 던진다. i == 42 는 Integerint 를 비교하는 것이다. 기본 타입과 박싱된 기본 타입을 혼용한 연산에서는 기본 타입의 박싱이 자동으로 풀린다. 그리고 null 참조를 언박싱하게되면 NPE가 발생하는 것이다.

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

다음 코드는 심각한 성능 저하를 유발한다. sum을 Long으로 선언했기 때문에 반복문을 돌 때마다 언박싱을 해야 하기 때문이다.

박싱된 기본타입을 사용해야 하는 경우

  • 첫 번째, 컬렉션의 원소,키,값으로 쓴다. 컬렉션을 기본 타입을 담을 수 없기 때문에 어쩔 수 없이 박싱된 기본 타입을 사용해야만 한다.
  • 두 번째, 리플렉션을 통해 메서드를 호출할 때도 박싱된 기본타입을 사용해야 한다.
profile
내 머릿속 지우개

0개의 댓글