자바의 모든 기본 타입(primitive type)에는 이에 대응하는 내장 래퍼(wrapper) 클래스가 존재하며, 이러한 래퍼 클래스들은 모두 불변(immutable)입니다. Integer, Float, Double, Byte 등이 대표적인 내장 래퍼 클래스에 해당합니다. 코드에서 래퍼 클래스를 사용하는 주된 이유는 크게 세 가지입니다. 첫째, 해당 기본 타입에 대한 타입 정보에 접근할 수 있고, 둘째, 기본 타입 데이터가 자동으로 객체 참조 타입으로 변환되는 오토 박싱(Auto-Boxing) 기능을 활용할 수 있으며, 셋째, 컬렉션과 같은 자료 구조 안에서 기본 타입 데이터를 손쉽게 다룰 수 있기 때문입니다.
래퍼 클래스의 인스턴스는 new 연산자를 사용해 생성할 수 있으며, Integer와 같은 타입이 제공하는 valueOf() 메서드를 활용해서도 래퍼 객체를 만들 수 있습니다. 특히 Integer.valueOf() 메서드는 힙(heap) 영역에 동일한 값을 가진 기존 Integer 객체가 있으면 이를 재사용합니다. 즉, 값이 같은 객체가 이미 존재하면 그 객체의 참조를 반환하고, 없을 경우 새로 생성된 Integer 객체의 참조를 반환합니다.
아래 코드 예제를 통해 JShell 도구에서 래퍼 객체를 생성하는 과정을 직접 확인해 보겠습니다.
예제 1
jshell> Integer int1 = new Integer(10); int1 ==> 10 jshell> Integer int2 = new Integer(10); int2 ==> 10 jshell> Integer int3 = Integer.valueOf(10); int3 ==> 10 jshell> Integer int4 = Integer.valueOf(10); int4 ==> 10 jshell> int1 == int2; $7 ==> true jshell> int3 == int4; $8 ==> true
예제 2
jshell> Integer abc1 = Integer.valueOf(700); abc1 ==> 700 jshell> Integer abc2 = 700; abc2 ==> 700 jshell> Integer abc3 = 700; abc3 ==> 700 jshell> abc2 == abc3 $4 ==> false jshell> Integer.MAX_VALUE $5 ==> 2147483647 jshell> Integer.MIN_VALUE $6 ==> -2147483648 jshell> Integer.SIZE $7 ==> 32 jshell> Integer.BYTES $8 ==> 4
예제 2에서 눈여겨볼 점은 abc2 == abc3의 결과가 false라는 것입니다. 오토 박싱 시 Integer는 -128부터 127까지의 값만 내부 캐시로 재사용하기 때문에, 700처럼 캐시 범위를 벗어나는 값은 박싱될 때마다 서로 다른 객체가 생성되어 참조 비교 시 false가 반환됩니다. 따라서 래퍼 객체의 값을 비교할 때는 == 연산자 대신 equals() 메서드를 사용하는 것이 안전합니다.