Java

자동 언박싱 프로세스 (Auto-unboxing process)

열심히 사는 우진 2023. 4. 13. 09:58
반응형

자동 언박싱 프로세스

자바의 primitive 타입은 Wrapper 타입으로 매핑될 수 있습니다.

int ↔ Integer

long ↔ Long 등..

 

primitive 타입을 써야할 때 Wrapper 타입을 사용하거나, 그 반대인 경우

자동으로 형이 타입이 변환됩니다.

 

Java 1.5부터 지원된 자동 언박싱 프로세스(Auto-unboxing process) 덕분인데요,

간단한 코드 예시로 알아보겠습니다.

public class Customer {
    private long id;
    private String firstName, lastName;

    public Customer(long id, String firstName, String lastName) {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
    }
}

위의 코드는, 예시코드에서 사용할 Customer 클래스입니다.

 

// primitive 타입 사용
long number = 1;
String firstName = "first";
String lastName = "last";
new Customer(number, firstName, lastName); // 생성 성공

// Wrapper 타입 사용
Long wrapperedNumber = new Long(1);
String firstName = "first";
String lastName = "last";
new Customer(wrapperedNumber, firstName, lastName); // 생성 성공

long 타입을 인자로 받는 Customer의 생성자에 Long 타입을 전달해도 생성에 성공합니다.

(반대의 경우에도 성공합니다.)

 

이렇게 필요한 경우에 long에서 Long으로, 혹은 Long에서 long으로 boxing 또는 unboxing하는 기능이 자바 내부적으로 지원됩니다.

Boxing, Unboxing 실행 시간

하지만 boxing, unboxing에 드는 리소스를 무시할 수 없습니다.

아래에서는 테스트 코드를 통해,

  • Primitive 타입만 사용했을 때
  • Boxing만 추가되었을 때
  • Unboxing만 추가되었을 때
  • Boxing / Unboxing이 모두 추가되었을 때

4가지 케이스에 대한 실행 시간을 측정해보겠습니다.

@Test
void 래퍼_클래스와_기본값_생성자에_인자로_전달_후_연산시간_비교() {

    String firstName = "first";
    String lastName = "last";

    long startTime;
    long endTime;

    //  Primitive 타입만 사용
    startTime = System.nanoTime();
    for (int i = 0; i < 100_000; i++) {
        long primitiveNumber = 1;
        new Customer(primitiveNumber, firstName, lastName);
    }
    endTime = System.nanoTime();
    System.out.println("Primitive 타입만 사용 : " + (endTime - startTime) + "ns");

    // Unboxing만
    Long wrapperNumber = new Long(1); // 시간 측정 전에 Boxing한 객체 생성
    startTime = System.nanoTime();
    for (int i = 0; i < 100_000; i++) {
        new Customer(wrapperNumber, firstName, lastName); // 생성자 내부에서 Auto unboxing
    }
    endTime = System.nanoTime();
    System.out.println("Unboxing만 : " + (endTime - startTime) + "ns");

    // Boxing만
    startTime = System.nanoTime();
    for (int i = 0; i < 100_000; i++) {
        Long wrapperNumberInner = new Long(1); // Boxing
        new Customer(1, firstName, lastName); // Boxing한 값 사용하지 않고 Primitive 타입 전달
    }
    endTime = System.nanoTime();
    System.out.println("Boxing만 : " + (endTime - startTime) + "ns");

    // Boxing + Unboxing
    startTime = System.nanoTime();
    for (int i = 0; i < 100_000; i++) {
        Long wrapperNumberInner = new Long(1); // Boxing
        new Customer(wrapperNumberInner, firstName, lastName); // 생성자 내부에서 Auto unboxing
    }
    endTime = System.nanoTime();
    System.out.println("래퍼 클래스로 생성 : " + (endTime - startTime) + "ns");
}

// 출력 :
// Primitive 타입만 사용 : 2721250ns
// Unboxing만 : 3207125ns
// Boxing만 : 4144833ns
// 래퍼 클래스로 생성 : 5515459ns

Auto unboxing, 그리고 Boxing을 통한 Wrapper 클래스 생성 모두 비용이 증가함을 알 수 있습니다.

생성 횟수에 비해 많이 차이나는 수준은 아니지만, 불필요한 Boxing과 Unboxing을 지양할 필요는 있을 것 같습니다.

 

감사합니다!

 

 

 

 

반응형