동일하다는 뜻으로 두 객체가 완전히 같은 경우를 의미한다.
완전히 같다는 것은 두 객체의 주소값이 같기때문에 같은 객체 즉 하나의 객체로 봐도 무방하다.
동일성을 판단하는 연산자는 ==연산자이며 Primitive타입의 객체는 주소가 없기때문에 같은 값을 가지면 동일하다고 본다.
동등하다는 뜻으로 두 객체가 같은 정보를 갖고 있는 경우를 의미한다.
동등성은 변수가 참조하고 있는 객체의 주소가 다르더라도 내용만 같으면 두 변수는 동등하다고 이야기할 수 있다. 동일하면 동등하지만 동등하다고 해서 동일한건 아니다. 동등성을 판단하는 연산자는 equals이다.
eqauls 연산자가 무조건 동등성을 판단하는것은 아니다. 모든 객체의 조상인 Object에서 정의하고 있는 equals 메서드를 봐보자.
public boolean equals(Object obj) {
return (this == obj);
}
반환형태를 보면 단순하게 동일성 비교를 하고 있다. 즉 ==연산자와 같은 역할을 하는것이다.
그렇다면 equals를 이용해 동등성을 어떻게 파악할 수 있을까?
오버라이드를 통해 재정의된 equals를 살펴보자.
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
동일하면 동등하기 때문에 ==연산자를 통해 동일성을 파악한다.
동일하지 않으면 String 문자열을 char형식으로 한글자씩 비교해 동등한지 비교한다.
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
Integer의 equals는 Integer인지 확인한 후 값을 비교해 동등한지 비교한다.
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
Objects 클래스에서 재정의한 equals를 보자.
a==b를 통해 동일성을 파악한다. 동일하지 않아도 또는 연산자를 통해 a과 b의 동등성을 파악한다. 여기서 equals는 a객체에서 재정의한 equals 통해 파악한다. 만약 a 객체에서 equals를 재정의하지 않았다면 Object equals를 사용하게 되어 동등성 대신 동일성을 파악하게 된다. 그렇기 때문에 커스텀 객체를 만들었을 때, equals를 쓰게된다면 꼭 재정의 과정이 필요하다.
객체를 collection에서 사용할 때, 동등성 비교가 가능할까?
Hash의 경우 어떤 데이터가 존재하는지 확인하기 위해 해싱 알고리즘을 사용한다. 해싱된 결과를 주소값으로 찾아가서 그곳에 같은 자료가 있는지 확인한다. 그 해싱 알고리즘에서 사용하는 데이터가 hashCode()이다.
Object의 hashCode()는 그 객체의 주소값을 반환하기 때문에(동일성) 동등성을 비교하기 위해선 hashCode를 재정의해야한다.
따라서, 객체의 동등성을 위해 equals메소드를 오버라이드하는 경우,
hashCode메소드도 오버라이드 해야 한다.
@Override
public int hashCode() {
return Objects.hash(name);
}
이렇게 해줘야 주소값이 아닌 name값으로 객체 비교가 가능하다.
<선생님들>
https://steady-coding.tistory.com/534
https://creampuffy.tistory.com/140