Wrapper 클래스와 정적 팩토리 메서드
📖 원시 타입(Primitive Type)
실제 값만을 저장하는 공간으로 스택 메모리 영역에 저장된다. 기본 값이 존재하기 때문에 null 값을 활용하고 싶다면 wrapper class를 활용해야한다.
타입 | 크기 | default | |
---|---|---|---|
논리형 | boolean | 1 byte | false |
정수형 | byte | 1 byte | 0 |
short | 2 byte | 0 | |
int | 4 byte | 0 | |
long | 8 byte | 0L | |
실수형 | float | 4 byte | 0.0F |
double | 8 byte | 0.0 | |
문자형 | char | 2 byte | ‘\u0000’ |
char 타입의 기본값은 널 문자로 참조형 변수인 널 값과는 다르니 헷갈리지 말자.
📖 참조 타입(Reference Type)
스택에 저장되어 있는 실제 값의 주소 값이 저장되는 타입으로 힙 메모리 영역에 저장된다.
기본값 | 할당되는 메모리 크기 | |
---|---|---|
Array | null | 4 byte |
Enum | null | 4 byte |
Class | null | 4 byte |
Interface | null | 4 byte |
⚠️ 참조 타입이라고 해서 call by reference 방식인 것은 아니다.
자바에서는 call by reference가 없다. 자바에서는 매개변수로 값을 넘길 때 변수 자체를 참조하는 것이 아니라 변수가 가리키는 주소를 복사해서 사용하기 때문에, 객체의 멤버 변수를 변경하면 해당 주소의 값이 바뀌어버리므로 변경이 적용되지만, 매개변수에 다른 객체 자체를 할당해봤자 전달한 인자의 참조는 변하지 않는다.
📖 Wrapper Class
Primitive Type의 데이터를 서로 형 변환이 가능하도록 지원해주는 클래스로써, 원시 타입의 자료형들을 클래스화한 것이다.
Primitive Type | Wrapper Class |
---|---|
int | Integer |
byte | Byte |
char | Character |
double | Double |
float | Float |
long | Long |
short | Short |
📝 래퍼 클래스(wrapper class) 사용 이유
-
매개변수로 객체가 요구될 때
-
기본형 값이 아닌 객체로 저장해야 할 때
-
객체 간 비교가 필요할 때
-
형 변환이 자유롭다
📝 박싱(Boxing) & 언박싱(UnBoxing)
📝 오토 박싱(AutoBoxing) & 오토 언박싱(AutoUnBoxing)
Integer num = new Integer(17); // 박싱
int n = num.intValue(); // 언박싱
Character ch = 'X'; // 오토박싱
char c = ch; // 오토언박싱
📝 Wrapper 클래스의 값 비교
-
래퍼클래스 == 기본타입 : true
auto unboxing 발생으로 기본타입끼리 계산
- 래퍼클래스.equals(기본타입) : true
-
래퍼클래스 == 래퍼클래스 : false
안에 든 값은 같아도 두 객체는 엄연히 다르다.
- 래퍼클래스.equals(래퍼클래스) : true
int value = 10;
Integer wrapper_value = new Integer(value);
Integer wrapper_value2 = new Integer(value);
System.out.println(wrapper_value == wrapper_value2); // false
System.out.println(wrapper_value.equals(wrapper_value)); // true
이렇게 선언을 하려고 해봤는데 9버전부터는 저런 식으로 박싱을 해주지 않는다고 한다…
Wrapper 클래스에서는 정적 팩토리 메서드를 제공해주는데, 이를 활용하여 인스턴스를 선언해주면 다음과 같다.
int value = 10;
Integer wrapper_value = Integer.valueOf(value);
Integer wrapper_value2 = Integer.valueOf(value);
System.out.println(wrapper_value == wrapper_value2); // true
System.out.println(wrapper_value.equals(wrapper_value)); // true
이렇게 정적 팩토리 메서드를 활용하면 미리 캐싱한 인스턴스를 리턴하기 때문에 일정 범위의 값에 대해서는 동일 객체를 반환한다. 따라서 ==로 비교해도 true가 리턴되는 것을 볼 수 있다.
📝 정적 팩토리 메서드(Static Factory Method)
정적 팩토리 메서드는 클래스의 인스턴스를 반환하는 정적 메서드를 의미한다.
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
다음은 Integer 클래스의 정적 팩토리 메서드 예시로, 정적 팩토리 메서드의 장점은 다음과 같이 볼 수 있다.
-
이름을 가질 수 있다.
생성자는 단순히 해당 클래스의 이름을 갖는데, 정적 팩토리 메서드를 사용해주면 그 이외의 이름을 가지기 때문에 동작의 의도를 더 잘 명시해준다.
-
호출할 때마다 인스턴스를 새로 생성하지 않아도 된다.
위의 코드와 같이 일정 범위의 값을 캐싱해놓음으로써 클래스의 필드값이나 구성요소를 변경할 수 없는 불변클래스 구현이 가능하다.
참고
댓글남기기