본문 바로가기

Java

[Java] Wrapper

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