자바에서 SerialVersionId 사용되는 예제를 보다가 @EqualsAndHashCode.include 라는 어노테이션이 붙어있길래, 해당 어노테이션이 어떤 것인지 궁금해졌다.

@EqualsAndHashCode 를 찾아보니 lombok 어노테이션으로 equals(Object other)hashCode() 를 생성해주는 어노테이션이었다.

equals와 hashCode는 모든 Java 객체의 부모 객체인 Object 클래스에 정의되어 있다. 그렇기 때문에 Java의 모든 객체는 Object 클래스에 정의된 equals와 hashCode 함수를 상속받고 있다.

equals()

Object 클래스에서 구현된 equals() 는 두 객체가 동일 객체인지 확인 하는 기능이다.

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

오로지 참조값(객체의 주소)가 같은지를 확인한다 (동일성)

하지만 자바에서는 보통 eqauls() 메소드는 두 객체의 동등성을 비교할 때 자주 사용한다. 다시 말해, 두 객체의 내부 value가 같은지를 확인하는 것으로 쓰인다. (String class의 equals)

그래서 내부 값이 같은지 비교를 원할 때는 해당 메소드를 override를 하면 된다.

String class의 eqauls 구현부를 보면 아래와 같다.

// String class
public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String aString = (String)anObject;
            if (coder() == aString.coder()) {
                return isLatin1() ? StringLatin1.equals(value, aString.value)
                                  : StringUTF16.equals(value, aString.value);
            }
        }
        return false;
    }

// StringLatin1 class
public static boolean equals(byte[] value, byte[] other) {
        if (value.length == other.length) {
            for (int i = 0; i < value.length; i++) {
                if (value[i] != other[i]) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }

우선 같은 객체인지 비교를 하고, 문자열 인코딩 방식에 따라서 내부 equals를 호출하는데 보면 각 바이트 값이 같은지를 확인한다. 즉 모든 문자가 같은지를 확인하게 된다.

hashCode()

객체 해시코드란 객체를 식별하는 하나의 정수값을 말한다. Object의 hashCode() 메소드는 객체의 메모리 번지를 이용해서 해시코드를 만들어 리턴하기 때문에 객체 마다 다른 값을 가지고 있다.

public native int hashCode();

여기서 native 키워드는 메소드가 JNI(Java Native Interface)라는 native code를 이용해 구현되었음을 의미한다. native는 메소드에만 적용가능한 제어자로, C or C++ 등 Java가 아닌 언어로 구현된 부분을 JNI를 통해 Java에서 이용하고자 할 때 사용된다. 우리같은 일반 개발자는 어디에서도 사용할 수 없다.

이러한 hashCode는 HashTable과 같은 자료구조를 사용할 때 데이터가 저장되는 위치를 결정하기 위해 사용된다.