박싱 타입 (Boxing type)
식별성을 가짐
같은 값을 가져도 다르다고 판단될 수 있음
필자) Wrapper class라고도 불리며 primitive type을 Wrapping한 클래스입니다 ex) Integer, Long
@Test
@DisplayName("Boxing된 기본 타입은 같은 값을 가져도 다르다고 판단될 수 있다")
void test() {
assertThat(new Integer(42) == new Integer(42)).isFalse();
}
필자)
간단한 테스트를 돌려봤습니다.
==는 내부에 동작된 equals가 동작하지 않고 주소값을 비교하기 때문에 같지 않다고 판단됩니다.
//in Integer.class
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
Integer 클래스는 equals가 override 되어있습니다. ==를 사용한 비교가 아닌 equals를 사용한 비교를 하면 같은 값이면 true를 반환합니다
NPE(Null Pointer Exceptoin)이 발생할 수 있다
public class Unbelievable {
static Integer i;
public static void main(String[] args() {
if (i == 42)
System.out.println("NPE!!!!")
}
}
위 상황에서 if문 안에서 NPE가 발생합니다
해당 테스트 작성
@Test
@DisplayName("null Integer과 기본 타입을 비교하면 NPE를 발생시킨다")
void test() {
Integer nullInteger = null;
assertThatThrownBy(() -> {
if (nullInteger == 42)
System.out.println("NPE!");
}).isInstanceOf(NullPointerException.class);
}
박싱된 타입과 기본 타입을 혼용한 연산에서는 박싱 타입이 자동으로 풀립니다.
null과 int를 비교하는 과정에서 Null Pointer Exception이 발생합니다.
굉장히 느리다
public static void main(String[] args) {
Long sum = 0L;
for (long i = 0; i <= Integer.MAX_VALUE; i++ {
sum += i;
}
}
위 과정에서 박싱과 언박싱이 반복되며 체감이 될 정도의 성능 문제가 발생함
박싱된 기본타입을 언제 써야할까?
컬렉션의 원소, 키, 값으로 사용
컬렉션은 기본 타입을 담을 수 없음
매개변수화 타입, 타입 매개변수로 사용
자바 언어가 타입 매개변수로 기본 타입을 지원하지 않음
ex) ThreadLocal<int> (X) ThreadLocal<Integer> (O)
리플렉션을 통해서 메서드를 호출할 때
요약
기본 타입과 박싱된 기본 타입 중 하나를 선택해야 한다면 가능하면 기본 타입을 사용하는게 좋음
기본 타입은 간단하고 빠름
블로그 필자 의견)
- 서비스를 만들면서 이런 부분이 성능적으로 큰 영향을 미치지는 않는 것 같음 (통신 오버헤드, 커넥션 오버헤드 등)
- 반복적으로 박싱과 언박싱을 반복하는 행위가 많이 발생하는 것은 조심해야함
- 아무 생각없이 박싱 타입을 하는 것 보다 nullable한 상황이 아니라면 기본값을 쓰는 것 정도로 유의하는게 좋은 것 같음
- 박싱 타입은 NPE, 식별성 문제를 주의하며 사용할 것