본문 바로가기
Language/Java

[Java API] 래퍼 클래스(Wrapper Class)

by 클레어몬트 2024. 8. 22.

ㅇ래퍼 클래스(Wrapper Class): 기본 자료형(Primitive Type)을 객체로 다룰 수 있게 감싸주는 클래스

자바에는 8개의 기본 자료형이 있는데, 이들은 객체가 아니기 때문에 객체지향 프로그래밍(OOP)에서 요구하는 여러 기능을 지원하지 않는다. 예를 들어, 기본 자료형은 컬렉션 프레임워크(e.g. ArrayList, HashMap)와 같은 자바의 API를 사용할 때 문제가 될 수 있다. 이 문제를 해결하기 위해 자바는 각 기본 자료형에 대응하는 래퍼 클래스를 제공한다.

 

간단한 활용 예시: 래퍼 클래스를 사용하여 기본 자료형을 ArrayList에 저장

import java.util.ArrayList;

public class WrapperClassExample {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(10); // 오토 박싱으로 Integer 객체로 변환되어 저장됨
        list.add(20);
        list.add(30);

        for (Integer num : list) {
            System.out.println(num); // 오토 언박싱으로 int 값으로 변환됨
        }
    }
}

 

위의 예시에서 ArrayList는 객체만 저장할 수 있기 때문에 int 값을 Integer 객체로 변환하여 저장하게 된다. 하지만 자바에서는 오토 박싱/언박싱을 통해 이러한 변환을 쉽게 처리해 준다.

 

 

기본 자료형과 대응하는 래퍼 클래스 8가지 (java.lang 패키지에 포함되어 있음)

  • byte -> Byte
  • short -> Short
  • int -> Integer
  • long -> Long
  • float -> Float
  • double -> Double
  • char -> Character
  • boolean -> Boolean

 

래퍼 클래스의 주요 기능

1. 객체화(Encapsulation): 래퍼 클래스를 사용하면 기본 자료형을 객체로 감쌀 수가 있다. 이를 통해 기본 자료형도 객체처럼 다룰 수 있게 된다.

int primitiveInt = 5;
Integer wrappedInt = Integer.valueOf(primitiveInt);

 

 

2. 기본 자료형과의 상호 변환: 래퍼 클래스는 기본 자료형 값을 객체로 변환(박싱, boxing)하고, 다시 기본 자료형으로 변환(언박싱, unboxing)할 수 있는 메서드를 제공한다.

int primitiveInt = 10;
Integer wrappedInt = Integer.valueOf(primitiveInt); // 박싱(기본 자료형 -> 객체)
int unwrappedInt = wrappedInt.intValue(); // 언박싱(객체 -> 기본 자료형)

 

 

3. 오토 박싱(Auto-boxing)과 오토 언박싱(Auto-Unboxing): 개발자들이 일일이 valueOf()와 xxxValue() 타자 치는 게 귀찮아서, Java 5(1.5)부터 도입됐다. 자바 컴파일러가 기본 자료형을 자동으로 래퍼 클래스 객체로 변환하거나, 래퍼 클래스 객체를 자동으로 기본 자료형으로 변환해 준다.

Integer wrappedInt = 10; // 컴파일러가 Integer.valueOf(10)으로 변환
int primitiveInt = wrappedInt; // 컴파일러가 wrappedInt.intValue()로 변환

 

 

4. 유틸리티 메서드: 래퍼 클래스는 기본 자료형과 관련된 여러 유틸리티 메서드를 제공한다. 예를 들어, Integer.parseInt(String s)는 문자열을 정수 기본형으로 변환하는 데 사용된다.

String numberStr = "100";
int number = Integer.parseInt(numberStr); // 문자열을 int로 변환

※ 기본적으로 parse(parsing, 파싱)는 문자열을 변환하는 데에 쓰이는 용어이다

 

 

5. 상수 필드: 래퍼 클래스는 해당 기본 자료형의 최댓값, 최솟값 등과 같은 유용한 상수 필드를 제공한다.

int maxInt = Integer.MAX_VALUE;
int minInt = Integer.MIN_VALUE;

 

 

래퍼 클래스의 주요 메서드

 - valueOf(): 래퍼 타입을 반환 (숫자, 문자열 모두 지원)

 

- parseInt(): 문자열을 기본형으로 변환

※ Long.parseLong() 처럼 각 타입에 맞는 parseXxx() 가 존재한다


- compareTo(): 내 값과 인수로 넘어온 값을 비교한다. 내 값이 크면 1, 같으면 0, 내 값이 작으면 -1을 반환

 

- Integer.sum(), Integer.min(), Integer.max(): static 메서드로, 기본 수학 연산을 제공

 

 

"parseXxx() vs valueOf()"

valueOf("10"): 래퍼 타입을 반환
parseXxx("10"): 기본형을 반환

 

 

[기본형과 래퍼 클래스의 성능 차이]

package lang.wrapper;

public class WrapperVsPrimitive {
    public static void main(String[] args) {
        int iterations = 1_000_000_000; // 숫자 리터럴에 언더스코어를 포함시켜 가독성 up
        long startTime, endTime;

        // 기본형 long 사용
        long sumPrimitive = 0;
        startTime = System.currentTimeMillis();
        for (int i = 0; i < iterations; i++) {
            sumPrimitive += i;
        }
        endTime = System.currentTimeMillis();
        System.out.println("sumPrimitive = " + sumPrimitive);
        System.out.println("기본 자료형 long 실행 시간: " + (endTime - startTime) + "ms");

        // 래퍼 클래스 Long 사용
        Long sumWrapper = 0L;
        startTime = System.currentTimeMillis();
        for (int i = 0; i < iterations; i++) {
            sumWrapper += i; // 오토 박싱 발생
        }
        endTime = System.currentTimeMillis();
        System.out.println("sumWrapper = " + sumWrapper);
        System.out.println("래퍼 클래스 Long 실행 시간: " + (endTime - startTime) + "ms");
    }
}

 

기본형 연산이 래퍼 클래스보다 대략 2.5배 정도 빠른 것을 확인할 수가 있다

기본형은 메모리에서 단순히 그 크기만큼의 공간을 차지한다. 예를 들어 int는 보통 4바이트의 메모리를 사용한다.  반면에, 래퍼 클래스의 인스턴스는 내부에 필드로 가지고 있는 기본형의 값뿐만 아니라 자바에서 객체 자체를 다루는데 필요한 객체 메타데이터를 포함하므로 더 많은 메모리를 사용한다. 자바 버전과 시스템마다 다르지만 대략 8~16 바이트의 메모리를 추가로 사용한다.

 

이 연산은 "10억 번의 연산을 수행했을 때" 0.5초와, 1.3초의 차이다. 기본형이든 래퍼 클래스든 이것을 1회로 환산하면 둘 다 매우 빠르게 연산이 수행된다0.3초 나누기 10, 1.5초 나누기 10억이다.
일반적인 애플리케이션을 만드는 관점에서 보면 이런 부분을 최적화해도 사막의 모래알 하나 정도의 차이가 날 뿐이다. CPU 연산을 아주 많이 수행하는 특수한 경우이거나, 수만~ 수십만 이상 연속해서 연산을 수행해야 하는 경우라면 기본형을 사용해서 최적화를 고려하자. 그렇지 않은 일반적인 경우라면 코드를 유지보수하기 더 나은 것을 선택하면 된다.

 

https://claremont.tistory.com/entry/%EC%9C%A0%EC%A7%80%EB%B3%B4%EC%88%98-vs-%EC%B5%9C%EC%A0%81%ED%99%94 

 

유지보수 vs 최적화

유지보수 vs 최적화를 고려해야 하는 상황이라면 유지보수하기 좋은 코드를 먼저 고민해야 한다. 특히 최신 컴퓨터는 매우 빠르기 때문에 메모리 상에서 발생하는 연산을 몇 번 줄인다고 해도

claremont.tistory.com

 

 

 

 

 

 

 

 

참고 및 출처: 김영한의 실전 자바 - 중급 1편

https://www.inflearn.com/course/%EA%B9%80%EC%98%81%ED%95%9C%EC%9D%98-%EC%8B%A4%EC%A0%84-%EC%9E%90%EB%B0%94-%EC%A4%91%EA%B8%89-1