[Java] Wrapper Class(래퍼 클래스)
자바의 자료형에는 총 8개의 기본 타입(primitive type)이 있다.
byte, short, int, long, float, double, char, boolean
이렇게 선언한 자료형을 특정 메소드의 매개변수로 집어넣고자 한다.
그런데 해당 메소드는 매개변수로 객체 형태만 받는다고 한다. 이럴 때는 기본 타입을 '객체화'해서 매개변수로 전달해야 하는데, 이때 필요한 것이 '래퍼 클래스(wrapper class)'이다.
1. Wrapper Class(래퍼 클래스)란?
여기서의 wrapper란 우리가 음식물을 포장할 때 쓰는 '래퍼(호일이라고 말하는 게 좀 더 이해하기 쉬우려나...?)'를 의미한다. 자바에 맞게 의역하면 기본타입을 객체 형태로 '포장'하는 것을 의미한다. 처음 래퍼 클래스라는 단어를 들었을 때 다소 생소하다고 느꼈는데, 생각보다 자신도 모르게 흔하게 쓰고 있었다(이게 정말 문제다).
① Generic(제네릭)
정해진 형식에 의존하지 않고, 클래스 외부에서 접근할 때의 재사용성을 높이 위해 사용하는 제네릭. 가령 ArrayList<Integer> xx처럼 컬렉션 형태의 변수를 선언할 때, 제네릭 타입의 <Integer>가 자바의 int 자료형과 매핑되는 래퍼 클래스이다.
② Casting(형 변환)
String 형태인 정수 타입의 변수를 int 형태의 기본 타입으로 casting 할 때, Integer 래퍼 클래스의 parseInt()라는 메소드를 사용하여 캐스팅을 진행한다.
String str = "2";
int strToInt = Integer.parseInt(str);
상단에 적어놓은 자바의 8개의 자료형은 다음과 같은 wrapper class와 서로 mapping 된다. 대부분 primitive 타입의 첫 글자만 대문자로 바꾼 형태지만, int, char만 예외적이니 이 두 개의 래퍼 클래스를 사용할 때만 유의하면 된다.
2. Boxing(박싱) vs Unboxing(언박싱)
Primitive type과 Wrapper class는 상호 변환이 이루어지는데, 이러한 과정을 각각 boxing과 unboxing이라고 칭한다.
boxing(박싱) : 기본 타입에서 wrapper 클래스로 전환
unboxing(언박싱) : wrapper 클래스 객체를 기본 타입으로 전환
변환의 방향에 따라 헷갈릴 수도 있지만, wrap = boxing으로 생각하면 너무나도 뚜렷하게 구분된다. 기본형을 래퍼 클래스로 바꾸는 것이 '포장된다'라는 의미이므로 박싱이고, 그 반대가 언박싱인 것이다. 박싱, 언박싱 방법은 기본형에 따라 큰 차이가 없이 대동소이하기에, 대표적으로 Integer ↔ int 간 언박싱/박싱 방법만 살펴본다.
먼저 Integer wrapper 클래스의 객체를 생성하는 박싱은, 기본 생성자의 매개 변수로 int 값을 넣어주는 것으로 간단하다.
Integer wrapper = new Integer(2);
반대로 wrapper 클래스 객체를 기본형으로 전환하는 방법은 다음과 같이 'intValue()' 메소드를 사용한다.
int primitive = wrapper.intValue();
다른 기본 자료형들도 마찬가지 '(자료형)Value()' 메소드로 언박싱을 할 수 있다.
Float a = new Float(9.5f);
byte num1 = a.byteValue();
short num2 = a.shortValue();
int num3 = a.intValue();
long num4 = a.longValue();
double num5 = a.doubleValue();
그런데 이런 경우가 발생하면 매번 박싱/언박싱을 해줘야 하는 걸까? 그래서 상단의 언박싱 메소드의 사용 없이 있는 그대로 객체를 기본 자료형에 대입하고 출력해보았는데, 아무런 오류가 발생하지 않았다.
int primitive2 = wrapper;
System.out.println("primitive2==>" + primitive2); // primitive2==>2
그 이유는 auto-boxing/unboxing이 가능하기 때문이다. JDK 1.5 버전부터 자동으로 이러한 작업들이 가능해짐으로써, 일일이 boxing/unboxing 하는 수고로움을 덜 수 있게 됐다. 그러고 보면 ArrayList<Integer>로 선언된 객체에 요소를 삽입할 때도 별도 boxing 없이 진행했었다.
ArrayList<Integer> IntArray = new ArrayList<Integer>();
intArray.push(1);
intArray.push(1);
intArray.push(1);
지금까지 자바의 wrapper class에 대해 알아보았다.
감사합니다 : )