동일성과 동등성은 객체를 비교할 때 중요한 방식이다.
자바에서는 두 개의 객체 또는 값을 비교할때 equals()또는==를 통해 구분할 수 있다.
1. equals와 ==의 차이
equals()는 객체의 내용을 비교하는 반면, ==는 객체의 참조주소를 비교한다. 따라서 두 객체의 내용이 같더라도 서로 다른 객체라면 equals()는 true를 반환할 수 있지만 ==는 false를 반환한다.
2. 동등성(Equality)
동등성은 논리적으로 객체의 내용이 같은지 비교한다. 이때 사용하는 equals()메서드는 클래스에서 오버라이드하여 어떤 값을 비교할 것인지 설정할 수 있다.이때 중요한건 객체의 equals뿐만 아니라 hashCode도 오버라이드를 해줘야 한다는 점이다.
그 이유는 해시값을 사용하는 자료 구조는 hashCode 메서드의 반환값을 사용하기 때문이다. hashCode 메서드의 반환 값이 일치한 이후 equals 메서드의 반환값이 참일 때에만 논리적으로 같은 값이라고 판단한다.
3. 동일성(Identity)
== 연산자를 사용하여 동일한 참조 주소를 갖는지 판단한다. String 클래스는 new 연산자로 새로운 문자열 객체를 만들지 않는 한 상수풀에 등록된 동일한 값을 사용하기 때문에 따로 값을 재정의하지 않아도 ==와equals()에서 동일한 값을 비교할 경우 true로 반환된다. 하지만 new연산자로 생성한 경우 에는 객체의 참조 주소값이 달라지기 때문에 ==에서 false가 발생한다.
public class Test{
private final int value;
public Test(int value){
this.value = value;
}
@Override
public boolean equals(Object o){
if (this == o) return true;
if (o== null || getClass() != o.getClass()) return false;
return value == o.value;
}
@Override
public int hashCode(){
return Objects.hashCode(value);
}
public static void main(String[] args){
Test testObject = new Test(1000);
Test newTestObject = new Test(1000);
System.out.println(testObject.equals(newTestObject)); //true
}
}
4. 만약 Wrapper 클래스라면?
래퍼 클래스 또한 객체이므로 ==연산자를 통해 참조 주소를 비교한다. 값 비교를 원할 경우에는 equals()메서드를 사용해야 한다.
자바는 특정 범위의 래퍼 객체를 캐싱하므로 같은 값의 객체가 같은 값을 참조하고 있을 수도 있다.
일반적으로는 equals()를 사용하는 것이 좋다.