Skip to content

Latest commit

 

History

History
111 lines (59 loc) · 3.39 KB

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

File metadata and controls

111 lines (59 loc) · 3.39 KB

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

자바는 두 가지 타입 시스템을 가지고 있다.

  • 기초 자료형(primitive types), int, double, boolean이 기초형에 속한다.
  • 레퍼런스 타입(reference types), List, Set 등이 레퍼런스에 속한다.

이중에서 기초 자료형의 오토박싱과 오토언박싱은 중요한 차이점이 있다.

기초자료형(primitive types)과 박싱된 기초자료형(boxed primitive types)에는 3가지 주요 차이점이 있다.

  1. 기초자료형은 값만을 가질 수 있다. 반면, 박싱 타입은 값 자체와는 구별되는 식별성(identity)을 갖는다.
  2. 기초자료형은 완전한 함수적 값이지만, 박싱 타입은 하나의 함수적이지 않은 값, null을 취급할 수 있다.
  3. 기초자료형은 박싱 타입보다 시간 효율성과 공간 효율성이 높다.

언제 박싱 타입을 사용하면 안되는가?

다음 코드는 두 정수값을 받아 비교하는 함수다. 이 코드의 문제점을 말할 수 있는가?

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

두 정수, 예를 들어 42를 동일한 두 인자로 전달하여 이 함수를 호출해보자.

naturalOrder.compare(new Integer(42), new Integer(42))

결과는 0을 기대했지만, 실제로 출력되는 값은 1이다.

이 코드의 문제는 == 에 있다. == 연산은 레퍼런스 타입일 경우 동일성(identity)를 판단한다.

따라서, 42라는 값에 대해 == 연산을 하는 것이 아니라, 레퍼런스의 동일성을 판단하는 것이다.

박싱 타입 == 을 사용하는 것은 거의 항상 잘못이다.

그렇다면, 이 코드를 정상적으로 동작하기 위해서 어떻게 수정해야할까?

박싱 타입을 언박싱하여 비교하면 된다!

Comparator<Integer> naturalOrder = (boxedI ,boxedJ) -> {
  int i = boxedI, j = boxedJ;
  return (i < j) ? -1 : (i == j) ? 0 : -1;
};

마지막으로 다음 코드의 문제점을 파악해보자.

	public static void main(String[] args) {
		long startTime = System.nanoTime();
		Long sum = 0L;
		for (long i = 0; i < Integer.MAX_VALUE; i++) {
			sum += 1;
		}
		long endTime = System.nanoTime();
		double elapsedTimeSeconds = (endTime - startTime) / (double) 1_000_000_000;

		System.out.println("how long did it take? : " + elapsedTimeSeconds + " seconds");
	}

문제는 매우 느리다는 것이다. 결과는 5초 가량이 소요된다.

how long did it take? : 5.332838373 seconds

main 함수의 두 번째 줄의 Long sumlong sum으로 바꾸어 결과를 확인하면, 1초 미만이 소요된다.

how long did it take? : 0.683741564 seconds

그럼 언제 박싱 타입을 사용해도 될까?

컬렉션의 항목/키/밸류에 사용한다. 파라미터화 타입(parameterized type)에는 기초 자료형을 사용할 수 없다.

ThreadLocal<int> 는 불가능하고 ThreadLocal<Integer> 로 작성해야 된다는 것이다.

정리

  • 박싱 타입은 값 타입이 아닌 레퍼런스 타입에 속한다.
  • 박싱 타입은 레퍼런스 타입이므로, == 연산 시에 동일성(identity)이 계산된다.
  • 박싱 타입은 연산이 매우 느리다.
  • 박싱 타입과 기초자료형을 섞어서 쓰면 안된다. 널 예외가 발생할 위험이 있다.