Skip to content

Latest commit

 

History

History
77 lines (65 loc) · 4.1 KB

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

File metadata and controls

77 lines (65 loc) · 4.1 KB

아이템 61: 박싱된 기본 타입보다는 기본 타입을 사용하라

Primitive Type And Reference Type

  • 자바의 데이터 타입은 크게 두가지
    • Primitive Type: int, double, boolean ...
    • Reference Type: String, List ...
  • 기본 타입에는 대응하는 참조 타입이 하나씩 있다.
  • 이를 박싱된 기본 타입이라고 한다.
    • int : Integer
    • double : Double

Primitive Type과 Reference Type의 차이점

  • 아이템 6에서 이야기 했듯 오토 박싱과 오토 언박싱 덕분에 두 타입을 크게 구분하지 않고 사용할 수 있다.
  • 그렇다고 차이가 사라지는 것은 아님
  • 차이점 1: 박싱된 기본 타입은 값에 더해 식별성 (identity)를 가짐
    • 달리 말하면 기본 타입의 두 인스턴스는 값이 같아도 서로 다르다고 식별될 수 있다.
  • 차이점 2: 박싱된 기본 타입은 유효하지 않은 값, 즉 Null을 가질 수 있다.
  • 차이점 3: 기본 타입이 박싱된 기본 타입보다 시간과 메모리 사용면에서 더 효율적이다.
  • 이상의 세 가지 차이 때문에 주의하지 않고 박싱된 기본 타입을 사용하면 진짜로 문제가 발생할 수 있다.

박싱된 타입을 사용하다 만날 수 있는 문제점 - 잘못 구현된 비교자

Comparator<Integer> naturalOrder = (i,j) -> (i < j) ? -1 : (i == j ? 0 : 1);
  • 위의 비교 구현자는 잘 구현된 듯 보인다.
  • 하지만 naturalOrder.compare(new Integer(42), new Integer(42))의 값을 출력해보자
  • 두 인스턴스의 값이 42로 같음으로 0을 출력해야 하지만 실제로는 1을 출력한다.
  • 즉, 첫 번째 Integer가 두 번쨰보다 크다고 주장한다.
  • 문제는 두 번쨰 검사에서 ==을 사용하면서 일어난다.
  • 참조 타입간 비교는 동등성이 아닌 동일을 비교함으로 같아야 하는 두 Integer가 다른 것 처럼 식별되게 되는 것

박싱된 타입을 사용하면 만날 수 있는 문제점 - 믿을 수 없군!

public class Unbelievable {
	static Integer i;
	
	public static void main(String[] args) {
		if (i == 42) {
			System.out.println("믿을 수 없군!");
		}
	}
  • 위 프로그램은 i == 42조건식을 검사할 때 NPE 발생
  • 원인은 i가 int가 아닌 Integer이며, 다른 참조 타입 필드와 마찬가지로 초깃값이 null이라는 것
  • 거의 예외 없이 기본 타입과 박싱된 기본 타입을 혼용한 연산에서는 박싱된 기본 타입의 박싱이 자동으로 풀린다.

박싱된 타입을 사용하면 만날 수 있는 문제점 - 끔찍이 느리다.

public static void main(String[] args) {
	Long sum 0L;
	for (long i = 0; i <= Integer.MAX_VALUE; i++) {
		sum += i;
    }
   System.out.println(sum);
}
  • 이 프로그램은 실수로 지역변수 sum을 박싱된 기본 타입으로 선언하여 느려졌다.
  • 오류나 경고 없이 컴파일 되지만 박싱과 언박싱이 반복해서 일어나 체감될 정도로 성능이 느려짐

세 문제점에 공통으로 적용될 수 있는 해결 방법

  • 이번 아이템에서 다룬 세 프로그램 모두 문제의 원인은 하나다.
  • 프로그래머가 기본 타입과 박싱된 기본 타입의 차이를 무시한 대가를 치른 것
  • 처음 두 프로그램은 뼈 아픈 실패로 이어졌고 마지막은 심각한 성능 문제가 발생했다.

박싱된 기본 타입은 언제 쓰나?

  • 박싱된 기본 타입도 적절히 쓰이는 경우가 있다.
  • 첫 번째: 컬렉션의 원소, 혹은 키, 값으로 쓴다.
    • 컬렉션은 기본 타입을 담을 수 없음
    • 자바 언어가 타입 매개변수로 기본 타입을 지원하지 않기 때문
  • 리플렉션을 통해 메서드를 호출할 때도 박싱된 기본 타입을 사용해야 함
  • nullable 함을 허용해야 할 때 (Entity의 id, Request DTO의 값 등등..)

We recommend that you declare consistently-named identifier attributes on persistent classes and that you use a nullable (i.e., non-primitive) type. link