작지만 꾸준한 반복

동일성? 동등성? equals? hashcode? 본문

공부기록/Java

동일성? 동등성? equals? hashcode?

iamjooon2 2023. 3. 1. 23:52

우아한테크코스 적응하는데 시간이 꽤 걸렸다

어느정도 적응했으니, 그동안 기술부채로 남겨둔 궁금한 것들을 시간나는대로 모두 정리할 것이다

 

이 블로그는 흔하디 흔한 개발자 이력서에 적을 보여주기식 블로그가 아닌

내가 다시 보고 싶어서, 내 멋대로 정리하고 적는 글들의 집합이다

잘 알아서 적는 것이 아닌, 잘 알고싶어서 쓰는 글들이다.

 

아무도 안보겠지만, 혹시 틀린 것이 있다면 지적해주시면 감사하겠습니다.

모든 원시값을 포장하라

우아한테크코스에서 강조하는 객체지향 생활체조 9가지 중 하나이다

 

저 요구사항을 만족시키기 위해 포장한 VO를 볼 때마다, 항상 equals, hashcode가 재정의 되어있었다

그리고 이에 대해 찾아보면 동일성과 동등성이라는 키워드가 꼭 하나씩 붙어있다

이건 대체 뭘까?

 

이름이라는 String 원시값을 포장한 Name이라는 클래스가 있다고 가정해보자.

생성자의 파라미터로 받은 String을 포장한다

 

Name name1 = new Name("준희");
Name name2 = new Name("준희");


name1 == name2 // false

 

name1과 name2는 같은 객체인가?

당연히 아니다

 

하지만 의미적으로, 두 객체는 같다

내가 임의로 정한 Name이란 클래스는 이름이라는 String을 포장하기 위한 값이므로

속에 담고있는 "준희"는 같아서, 사실상 같은 의미이다

 

동일성과 동등성은 바로 이것이다

name1과 name2는 다른 객체이므로 동일하진 않지만,

사실상 같은 값을 같고 있기에 동등하다고 한다.

 

동일성은, 두 객체가 가르키는 메모리 주소가 같음을 뜻하고,

동등성은, 두 객체가 의미적으로 같음을 뜻한다

 

그렇다면 equals, hashcode는 뭘까?

뭔데 override 할 수 있을까?

 

equals와 hashcode는 무려 자바 1(.......)에 등장한 Object클래스에 정의되어있는 넘이다...

그리고 이 Object 클래스는 모든 자바 컬렉션의 부모클래스이므로... 어떤 클래스에서든지 다 상속할 수 있다...

https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html

 

Object (Java SE 17 & JDK 17)

java.lang.Object public class Object Class Object is the root of the class hierarchy. Every class has Object as a superclass. All objects, including arrays, implement the methods of this class. Since: 1.0 See Also: Constructor Summary Constructors Method S

docs.oracle.com

 

그러면, 왜 얘네를 재정의하는걸까?

 

먼저 Object 클래스의 equals를 뜯어보자

public boolean equals(Object obj) {
    return (this == obj);
}

== 연산자로 단순히 두 객체의 동일함을 비교하고 있다

 

맨 처음 나온 name1과 name2를 equals를 사용해 비교한다면,

당연히 같지 않다 말할 것이다.

 

VO에서 필요한 것은 두 객체가 동일함이 아닌 동등함이므로

equals를 override 하여, 두 객체가 동등한지를 비교할 수 있도록 한다

 

자 그럼 equals는 뭔지 알겠는데, hashcode는 뭘까?

hashcode는 hash값을 사용하는 Collection(hashmap, HashTable, HashSet)에서 hashcode를 재정의하지 않고 equals를 사용시 문제가 일어날 수 있기에 재정의한다.

 

hash값을 사용하는 Collection에서, 객체가 논리적으로 같은지 비교하는 과정에서 hashCode를 사용한다

내가 포장한 VO가 언제든 Hash Collection에 쓰일지 모르니, 그냥 인텔리제이 자동완성 써서 바로 재정의하자.

내가 쓸때 재정의해야지! 라고 생각해도, 내 동료는 그렇게 생각하지 않을 수도 있다...

 

인텔리제이의 자동완성 기능을 이용하여, equals와 hashcode를 재정의해보았다

@Override
    public boolean equals(final Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        final Name name1 = (Name) o;
        return Objects.equals(name, name1.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name);
    }

 

내맘대로 결론

 

같은 메모리 주소를 가르킬 때 동일하다고 한다

의미적으로 같으면 동등하다고 한다

equals와 hashcode, 일단 재정의하자. 인텔리제이가 다 해준다