티스토리 뷰

반응형

자바의 데이터 타입

  • 기본 타입 : int, double, boolean 등
  • 참조 타입 : String, List
  • 각각의 기본타입에 대응하는 참조 타입이 하나씩 있음 → 박싱된 기본 타입 (Integer, Double, Boolean)
  • 오토박싱과 오토언박싱 덕분에 두 타입을 크게 구분하지 않고 사용할 수 있지만, 둘 사이엔 분명한 차이가 있으니 뭘 사용하는진 매우 중요

 

기본 타입 vs 박싱된 기본 타입

1) 기본 타입은 값만 가지고 있지만, 박싱된 기본 타입은 값에 더해 식별성(identity)이란 속성도 갖고 있음

박싱된 기본 타입의 두 인스턴스는 값이 같아도 서로 다른 인스턴스라고 식별됨 ( == 로 비교시)

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

naturalOrder.compare(new Integer(42), new Integer(42));  // 1 반환

위 코드에서 두 Integer 인스턴스의 값이 42로 같으므로 0을 반환해야하지만, 실제로는 1을 반환한다.

naturalOrder의 ( i < j ) 에서는 오토박싱에 되어 기본 타입값으로 변환되어 비교하기 때문에 잘 작동한다.

그런데 ( i == j ) 에서는 두 객체 참조의 식별성을 비교하게 된다.

그래서 두 인스턴스가 42로 값이 같더라도 서로 다른 인스턴스이기 때문에 같지 않다고 판단하는 것이다.

→ 박싱된 타입의 값을 비교하고 싶다면 == 연산자를 사용하면 안되고 equals 를 사용해야한다.

 

 

2) 기본 타입의 값은 언제나 유효하지만, 박싱된 기본타입 값은 유효하지 않은 null 도 가질 수 있음

public class Unbelievable {
    static Integer i;

    public static void main(String[] args) {
        if(i == 42)
            System.out.println("믿을 수 없군!");
    }
}

위 코드의 결과는 NullPointerException을 던지는 것이다.

다른 참조 타입 필드와 마찬가지로 i의 초깃값도 null이기 때문이다.

기본 타입과 박싱된 기본 타입을 혼용한 연산에서는 박싱된 기본타입의 박싱이 자동으로 풀린다. → i 를 int 로 선언하자.

 

 

3) 기본 타입이 박싱된 기본 타입보다 시간 및 메모리 사용면에서 더 효율적

위 차이 때문에 두 타입을 주의하지 않고 사용하면 문제가 발생할 수 있다.

//심각한 성능 문제 발생
public static void main(String[] args) {
        long startTime = System.nanoTime();
        Long sum = 0L;
        for (long i = 0; i < Integer.MAX_VALUE; i++) {
            sum += 1;
        }
    System.out.println(sum);
}

위 코드는 지역변수 sum을 박싱된 기본 타입으로 선언하여 느려졌다.

오류나 경고 없이 컴파일되긴하나 박싱과 언박싱이 반복해서 일어나면서 성능이 매우 느려진다.

이렇게 기본타입과 박싱된 기본 타입의 차이를 무시하면 대가를 치르게 되니 주의해서 선택해서 사용하자.

 

 

박싱된 기본 타입을 써야하는 때

박싱된 기본 타입이 적절히 쓰이는 경우가 몇가지 있다.

  • 컬렉션의 원소, 키, 값으로 쓰인다. 즉, 매개변수화 타입이나 매개변수화 메서드의 타입 매개변수로는 박싱된 기본 타입을 써야함 (자바가 타입 매개변수로는 기본 타입을 지원하지 않아서)
  • 리플렉션 [아이템 65] 을 통해 메서드를 호출할 때도 박싱된 기본 타입을 사용해야함

 

결론

  • 기본 타입과 박싱된 기본 타입 중 가능하면 기본 타입을 사용하라. (간단하고 빠름)
  • 오토박싱이 박싱된 기본 타입을 사용할 때 번거로움을 줄여주긴하나 그 위험까지 없애주진 않는다. (주의 기울여 사용)
  • 두 박싱된 기본 타입을 == 연산자로 비교한다면 값의 비교가 아니라 식별성 비교가 이뤄져 오류가 남 → equals 사용
  • 기본 타입과 박싱된 기본 타입을 혼용하면 언박싱이 이뤄지고 이 과정에서 NullPointerException을 던질 수 있으니 주의
  • 기본 타입을 박싱하는 작업은 필요 없는 객체를 생성하는 부작용 주의
반응형
댓글
반응형
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday