article thumbnail image
Published 2022. 7. 14. 20:06

equals()

  • 클래스 Obejct에 대한 equals 메소드는 객체에 대해 등가 관계를 구현한다. 즉 null이 아닌 참조 값 x 및 y가 동일한 객체를 참조하는 경우에만 true를 반환한다.
class Person {
	private int age;
	private String name;

	public Person(int age, String name) {
			this.age = age;
			this.name = name;	
	}
}
public static void main(String[] args) {

    Parent person = new Parent(19, "lala");
    Parent person1 = new Parent(19, "lala");

    System.out.println(person.equals(person1)); //false
}

 

person.equals(person1) 왜 결과가 false일까?

 

Obejct의 equals 메소드 정의를 보면 다음과 같다

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

단순히 Object의 ==로 비교하는 것을 확인할 수 있다. “값"을 비교하는 것이 아니라 “주소값” 즉 hashCode를 비교하고 있는 것이다.

이 문제를 해결하기 위해서는 equals()를 Override해야 한다.

@Override
public boolean equals(Object obj) {

    if (obj == null) {
        return false;
    }

    if (this.getClass() != obj.getClass()) {
        return false;
    }

    if (this == obj) {
        System.out.println("Object Same");
        return true;
    }

    Person that = (Person) obj;

    if (this.name == null && that.name != null) {
        return false;
    }

    if (this.age == that.age && this.name.equals(that.name)) {
        System.out.println("Object Value Same");
        return true;
    }

    return false;
}

equals() 메서드를 overriding할 때 반드시 지켜야할 조건

  1. 재귀: null이 아닌 x라는 객체의 x.equals(x) 결과는 항상 true여야만 한다.
  2. 대칭: null이 아닌 x와 y객체가 있을 때 y.equals(x)가 true를 리턴했따면, x.equals(y)도 반드시 true를 리턴해야만 한다.
  3. 타동적: null이 아닌 x,y,z가 있을 때 x.equals(x)가 true를 리턴했다면, y.equals(z)가 true를 리턴할 때 x.equals(z)는 반드시 true를 리턴해야만 한다.
  4. 일관: null이 아닌 x와 y가 있을 때 객체가 변경되지 않은 상황에서는 몇 번을 호출하더라도 결과가 항상 true이거나 false여야만 한다.
  5. null과의 비교: null이 아닌 x라는 객체의 x.equals(null) 결과는 항상 false여야만 한다.

 

hashCode()

  • hashCode 메소드는 실행 중에(Runtime) 객체의 유일한 정수 값을 반환한다.
  • Object의 hashCode() 메서드는 객체의 메모리 번지를 이용해서 해시코드를 만들어 리턴하기 때문에 객체마다 다른 값들을 가지고 있다.
  • 어떠한 객체와 다른 객체의 equals 결과가 true라면 그 둘의 hashCode 값은 반드시 같아야 한다.
  • equals가 두 객체를 다르다고 판단했더라도, 두 객체의 hashCode가 서로 다른 값을 반환할 필요는 없다. 단 다른 객체에 대해서는 다른 값을 반환해야 해시 테이블의 성능이 좋아진다.

 

 

public static void main(String[] args) {

    Person person1 = new Person(18, "kim");
    Person person2 = new Person(18, new String("kim"));
	Person person3 = person1;

    System.out.println(person1.hashCode()); // 151029101
	System.out.println(person2.hashCode()); // 234321212
	System.out.println(person3.hashCode()); // 234321212
}

 

위의 코드에 대한 StackHeap 메모리 할당 구조는 다음과 같다.

 

 

'자바' 카테고리의 다른 글

JVM, JDK, JRE, JIT  (0) 2022.07.18
Call by Value와 Call by Reference  (0) 2022.07.14
String의 특징  (0) 2022.07.14
복사했습니다!