래퍼 클래스(Wrapper Class)

Wrapper Class

자바의 자료형은 크게 기본형과 참조형으로 구분된다. 참조형은 참조 주소를 가리키는 데이터 타입이고, 기본형은 실제 값을 갖는 데이터 타입이다.

참고 : DevAndy - 자바 데이터 타입, 변수 그리고 배열

기본형 타입을 객체로 사용해야할 때가 있는데, 이 때 사용되는 데이터 타입이 Wrapper Class이다. 다른 말로 포장객체라고도 한다.

Wrapper Class는 참조형 타입에 해당한다. 아래의 테이블을 통해서 기본형과 Wrapper 클래스를 구분하도록 하자.

기본형 Wrapper Class
byte Byte
char Character
int Integer
float Float
double Double
boolean Boolean
long Long
short Short

출처 : 코딩팩토리 - 래퍼 클래스란 무엇인가 (박싱, 언박싱)


Boxing, UnBoxing

포장객체(Wrapper Class)란, 기본형 타입의 데이터를 객체형 타입으로 감싼걸 의미한다. 이 과정을 Boxing이라고 한다.

  • Boxing ➡️ 기본형 타입의 데이터 값을 객체화하는 과정
  • UnBoxing ➡️ 포장객체에서 기본 타입의 값을 얻어오는 과정

사용 예제

아래의 코드를 통해 확인해보자.

1
2
3
4
5
6
7
8
9
10
public class DevAndy {
public static void main(String[] args) {
String str1 = new String("hello");
String str2 = "hello";
String str3 = "hello";

System.out.println(str1==str2);
System.out.println(str2==str3);
}
}

위의 코드에서 main 메소드를 실행하면 콘솔에 어떻게 출력될까?

1
2
false
true

str1==str2false를 반환했고, str2==str3true를 반환했다. 이유를 알아보자.

== 연산자는 객체의 주소값을 비교하는 연산자인데, false 를 반환했다는 것은 비교하는 두 객체의 주소값이 달랐을것으로 추론된다. 실제로 주소값을 콘솔에서 확인해보자.

1
2
3
4
5
6
7
8
9
10
11
12
public class DevAndy {
public static void main(String[] args) {
String str1 = new String("hello");
String str2 = "hello";
String str3 = "hello";
// System.out.println(str1==str2);
// System.out.println(str2==str3);
System.out.println("str1 identity hashcode : "+System.identityHashCode(str1));
System.out.println("str2 identity hashcode : "+System.identityHashCode(str2));
System.out.println("str3 identity hashcode : "+System.identityHashCode(str3));
}
}
1
2
3
str1 identity hashcode : 1057941451
str2 identity hashcode : 434091818
str3 identity hashcode : 434091818

정말 주소값이 달랐다. 그래서 포장객체와 기본형 타입의 값을 비교했을때, false 를 반환한 것이다. 이럴땐 어떻게 비교해야할까? String 클래스에는 값만을 비교할때 사용하는 equals()가 있다.

1
2
3
4
5
6
7
8
9
10
public class DevAndy {
public static void main(String[] args) {
String str1 = new String("hello");
String str2 = "hello";
String str3 = "hello";

System.out.println(str1.equals(str2));
System.out.println(str2.equals(str3));
}
}
1
2
true
true

이번엔 모두 true를 반환받을 수 있었다.

이유는 위의 변수들중 포장객체와 기본형 변수의 identity hashcode는 서로 달랐지만, hashCode는 같았기 때문이다. 이게 무슨 말일까?

  • System.identityHashCode(str)
    • identity hashcode는 파라미터로 들어온 객체의 고유한 값을 반환한다.
  • str.hashCode()
    • Object에서 정의하고 있는 메소드로써 String 클래스에서 hahsCode()를 오버라이딩하기 때문에 고유한 값이 다르더라도 값이 같다면, 같은 주소값을 공유하게 된다.

identityHashCode()는 재정의(Override)되지 않는 고유한 주소값을 반환하는 함수이고, hashCode()는 String 클래스에서 재정의한 주소값을 공유하기 때문에 타입이 달라도 equals()로 기대한 결과를 반환받을 수 있던 것이다.

출처 : chacha - System.identityHashCode()와 hashCode()의 차이점

hashCode()는 아래와 같은 로직으로 String 내부에서 오버라이딩된다고 한다.

1
2
3
4
5
6
7
8
9
10
11
public int hashCode() {
int h = hash;
if(h==0 && value.length>0) {
char val[] = value;
for(int i=0; i<value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}

References