Blog
스터디
CS Study with SON
6주차
equals와 hashcode

Equals()와 Hashcode()

equals()와 Hashcode는 모든 Java 객체의 부모 객체인 Object 클래스에 정의되어 있다. 따라서 Java의 모든 객체는 두 함수를 상속받고 있다.


== 연산자

  • primitive type에 대해선 값 비교를, reference Type에 대해서는 객체의 주소 값을 비교함
    • 원시 타입(Primitive type)
      • 기본적인 데이터 타입으로, 자바에서 미리 정의되어 있는 데이터 타입
      • 빈 객체 타입으로 NULL값을 가질 수 없으며 Stack메모리 저장
    • 참조 타입(Reference Type)
      • 객체를 가리키는 참조(메모리 주소)를 저장하는 데이터 타입
      • 빈 객체 타입 NULL을 가질 수 있으며 Heap 메모리에 생성


equals()

// Object의 기본 equals 메서드
public boolean equals(Object obj) {
    return (this == obj);
}
  • 개념
    • 어떤 두 참조 변수 값의 동등여부를 비교할 때 사용하는 매소드
      • 동일성(Identity) 비교
    • 어떤 두 객체가 가리키는 곳이 동일한 메모리 주소일 경우에만 동일한 객체로 판단
  • 특징
    • java.lang.Object 클래스에 정의
    • equals 메소드의 기본동작은 객체의 참조값을 비교하나, 객체의 내부 값을 비교하기 위해 논리적으로 재정의(override) 될 수 있음
  • 주의사항
    • Null의 처리
      • equals() 메서드는 null과의 비교도 처리할 수 있어야 함
      • null과는 항상 false를 반환
      • null인지 검사하여 NullPointerException이 발생하지 않도록 주의
    • 타입체크
      • 매개변수로 전달된 객체가 현재 객체와 동일한 클래스(또는 하위 클래스)의 인스턴스인지 확인
    • 상속과 호환성
      • 부모 클래스의 equals() 메서드도 동작하도록 super.equals()를 호출하거나 부모 클래스의 동치성 비교에 필요한 속성들을 자식 클래스에서 고려

equals 메소드 오버라이딩

  • 프로그래밍 시 동일한 객체가 메모리 상에 여러 개 띄워져 있는 경우가 존재함
    • 해당 객체가 서로 다른 메모리에 띄워져있을 경우 동일한(Identity) 객체가 아님
  • 하지만 프로그래밍 상으로 같은 값을 지님으로 같은 객체로 인식되도록 처리하고 싶은 상황이 존재할 수 있음
    • 이런 동등성(Identity)을 위해, 값으로 객체를 비교하도록 equals 매소드 오버라이딩을 진행함
  • EX) 동일한 값을 갖는 문자열 2개에 대한 equals() 호출
    • 두 문자열은 서로 다른 메모리에 할당되어 동일하지 않으나, 같은 값을 가져 동등함
    • String 클래스에서 equals매소드 오버라이드 진행
      • 객체가 같은 값을 갖는지 동등성(Equality)을 비교하도록 처리
    • 동일성을 비교하는 equals 메소드 호출 시 true 반환


Hash code

native 키워드
: 메소드가 JNI라는 native code를 이용해 구현되어 있음을 의미하며, OS에 C언어로 작성되어있어 그 안의 내용은 볼 수 없고 사용만 가능하다. hashCode()는 native 코드 중 하나이다.


public native int hashCode();
  • 개념
    • 객체의 주소 값을 이용해서 해싱(hashing) 기법을 통해 반환한 해시 코드로 객체를 식별하는 하나의 정수 값
  • 특징
    • java.lang.Object 클래스에 정의
    • 객체의 메모리 번지를 이용해 해시코드를 만들어 리턴하므로 객체마다 다른 값을 가짐
      • 주소값으로 만든 고유한 숫자값
  • 재정의 시, 고려사항
    • 객체 상태 기반 해시코드 생성
      • 객체의 필드들이 모두 hashCode에 반영되어야 함
      • 객체가 가지는 모든 중요한 정보 고려해야 함
    • 불변성
      • 객체의 상태가 변경되지 않으면 hashCode()의 결과도 변하지 않아야함
    • 충돌 최소화
      • 서로 다른 객체가 동일한 해시값을 갖지 않도록 충돌을 최소화하는 해시함수 선택

equals와 hashCode

자바 규칙
equals()의 결과가 true인 두 객체의 해시코드는 반드시 같아야 한다.

  • Hash값을 사용하는 Collection 객체의 논리적 비교
    1. HashCode() 리턴 값 비교
      • 리턴 값 다름 → 다른 객체
      • 리턴 값 같음 → equals()
    2. equals() 리턴 값 비교
      • 리턴 값 다름 → 다른 객체
      • 리턴 값 같음 → 동등 객체

Hash값을 재정의 하지 않을 경우

  • hash값을 사용하는 Collection Framework(HashSet, HashMap, HashTable)에서 객체 비교를 진행함
  • 이때 hashCode 메서드를 재정의 하지 않았으므로, HashCode() 리턴 값 비교 과정에서 Object 클래스의 hashCode 메서드를 사용함
    • 같은 객체여도 equals()로 비교하기 전에 서로 다른 hashcode 메서드의 값이 리턴되어 다른 객체로 판단 됨
  • 위와 같은 이유로 equals와 HashCode의 값을 같이 재정의 해야 함


identity HashCode 메소드

System.identityHashCode(p1);
  • 개념
    • hashCode()를 오버라이딩 해서 쓰되, 오버라이딩 하기 전의 원조 기능이 필요할 때 사용 하는 메서드
  • 배경
    • HashCode의 본래 목적은 객체의 주소값을 기반으로 해싱한 고유 숫자 값을 바탕으로 객체가 동등한지 여부를 판단하는 것
    • 하지만 equals()와 hashCode() 메서드를 오버라이딩할 경우, 본래 목적인 객체 자체의 해시코드를 얻을 수 없음
    • 따라서 자바에서는 똑같이 해시 코드를 반환해주는 identityHashCode() 코드를 만들게 되었음