Wrapper
자바에는 크게 2가지 자료형으로 구분할 수 있습니다.
기본 타입인 Primitive Type 과 참조 타입인 Reference Type 입니다.
여기서 기본타입은 int, double, float, boolean등이 있는데 이를 객체로 표현화한 것을 Wrapper 클래스 라고합니다.
Primitive Class | Wrapper class |
byte | Byte |
char | Character |
int | Integer |
float | Float |
double | Double |
boolean | Boolean |
long | Long |
short | Short |
Wrapper 클래스의 종류는 위와같이 존재하고 Primitive Type에서 Wrapper Type으로 만드는 과정을 Boxing, Wrapper Type에서 Primitive Type으로 만드는 과정을 unBoxing 이라고 표현합니다.
public static void main(String[] args) {
Integer wrapper = new Integer(55); // Boxing
int primitive = wrapper.intValue(); // UnBoxing
}
또한 AutoBoxing , AutoUnBoxing 이라는 개념이 있습니다.
직접 위와같은 작업을 해주지않아도 자동으로 Boxing과 UnBoxing이 일어나는 경우를 이야기합니다.
이와 같이 AutoUnBoxing이 있기에 UnBoxing 과정을 제거해도 됩니다.
==, Equal, HashCode
Wrapper 클래스를 설명하며 한가지 더 연관지어 설명하고 싶은 내용입니다.
흔히 객체와 객체 또는 변수와 변수를 비교할 때 사용되어지는 방식들인데요.
위의 코드는 모두 예상하신대로의 결과가 나왔습니다. 뭐 이런걸 보여주나 싶을텐데요.
그럼 아래의 결과는 어떻게 나올까요?
직접 해보시면 아시겠지만 false 이 나옵니다. 도대체 어떻게 이런일이 가능할까요?
결론부터 말하면 "==" 는 "1" 이라는 문자열을 비교하는 의미가 아니라 해당 주소값을 비교하는 연산자입니다.
그럼 첫번째 그림의 one과 two는 어떻게 true가 나왔냐는 질문이 올 수 있습니다.
그 이유는 위 변수에 저장된 "1"은 자바의 Stack 영역에 저장되게 되는데 이때 다른 변수가 같은 상수값을 가지고 있다면 그 주소값을 그대로 갖게됩니다. 그래서 true 라는 결과가 나올 수 있던것이죠.
그럼 new String은 뭘까요?
제 블로그 메모리영역과 Garbage Collection을 잘 봤다면 뭔가 생각난게 있을텐데요.
new 를 통해 생성된 변수는 Stack이 아니라 Heap 영역에 저장된다고 했었습니다.
그렇다면 결론은 new 를 통해 생성했기 때문에 새로운 주소값을 할당받았다 라는 결론이 나오게 되겠지요.
그럼 다음 질문을 해볼게요. Wrapper 클래스끼리의 비교입니다.
결과는 무엇일까요? 위의 과정을 이해했다면 당연히 false이 나왔을거라 생각합니다.
이처럼 Wrapper 클래스끼리의 비교는 ==로는 해결할 수 없습니다.
이는 객체 또한 마찬가지인데요. 실험에 쓸 객체를 하나 만들어봅시다.
public class Car {
private int price;
private int weight;
public Car(int price, int weight) {
this.price = price;
this.weight = weight;
}
}
다음의 결과는 어떻게 나올까요?
결과는 모두 false입니다. 믿었던 equals와 hashCode 마저 false 이라는 결과를 만들어냅니다.
그럼 우리에게 객체비교에 대한 해답은 없는걸까요? 그 이유는 무엇일까요?
해결법을 찾기위해 이유를 찾아봅시다.
결과부터 이야기하면 equals 와 hashCode는 모두 동작시키는 대상안에 주소값도 포함되어있습니다.
위에서 글을 읽으며 one과 two의 주소값이 다르다는것쯤은 알고계셨을텐데요.
그렇기에 eqauls와 hashCode를 Override을 통해 재정의 하면 문제를 해결할 수 있습니다.
@Override
public boolean equals(Object o){
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Car car = (Car) o;
return this.price == car.price && this.weight == car.weight;
}
@Override
public int hashCode(){
return Objects.hash(this.price, this.weight);
}
Car 라는 클래스안에 이런식으로 재정의를 해줄게요. 원래는 저 과정에 price와 weight 말고도 주소라는 값까지 포함되어있다라는것 꼭 알아두세요.
어쨋든 해당 함수를 작성하고 나면 아래의 결과를 볼 수 있을거에요.
'Java' 카테고리의 다른 글
[Java] 멀티스레드와 동시성 (0) | 2024.09.14 |
---|---|
[Java] 자바의 Compiler (1) | 2024.09.08 |
[Java] Optional (0) | 2023.03.15 |
[Java] 메모리 영역과 Garbage Collection (0) | 2023.03.14 |
[Java] JRE, JDK, JVM (0) | 2023.03.14 |