-
equals
가 뭐야?equals
객체 끼리 내용을 비교할 수 있게 만드는 공통 메서드 ( Object 클래스에 정의되 있음 )==
과의 차이는 ?equals
는 논리적 동치성을 확인할 때 사용. 객체의 내용이 같은지 확인 ( 재정의 시 )- 논리적 동치성 : 논리적으로 같은지 확인함 ( 동등성 )
==
는 객체 식별성 ( 물리적으로 같은가 , 동일성)를 확인할 때 사용. 주소값이 같은지 확인
- equals 재정의 하는 이유? 논리적 동치성을 표현하기 위해서!
-
언제
equals
를 재정의할까? -
equals
를 정의하지 않는 것이 좋을 때- equals 재정의는 자칫 실수할 우려가 있음
- 잘못 구현해놓으면 당연히 일반 규약들을 지키고 있는 줄 아는 클래스들(List, Set 등)에 영향을 줌 → 어떻게 반응할 지 모름
- 오히려 잘못 구현하는 것보다 그냥 재정의 안하고 그냥 두는게 가장 최선일 수 있음
- 각 인스턴스가 본질적으로 고유할 때
- 값을 표현하는 객체가 아닌 동작하는 객체를 표현하는 클래스(Like Thread)의 경우
- 인스턴스의 논리적 동치성을 검사할 일이 없을 때
- 상위 클래스에서 재정의한 equals가 하위 클래스에도 딱 맞을 때
- 클래스가 private 이거나 package-private 이고 equals 메서드를 호출할 일이 없을 때
- equals 재정의는 자칫 실수할 우려가 있음
-
equals
재정의 할 때 지켜야할 일반 규약equals
는 동치관계를 구현하므로 일반 규약을 만족해야함
- 반사성
x.equals(x)는 true다. (x 는 not null)
- 일반적으로 만족시키지 않는게 더 힘듬.
- 대칭성
- 추이성
- 일관성
x.equals(y)를 반복해서 호출하면 항상 true or 항상 false를 반환한다. (x, y는 not null)
- 가변 객체는 비교 시점에 따라 서로 다를 수도 같을 수 있다. 하지만 불변 객체는 한번 다르면 끝까지 달라야 한다.
- null-아님
x.equals(null)은 false이다. (x는 not null)
- 모든 객체가 null과 같지 않아야 한다
- 보통
equals
내부에서 명시적으로if (o == null)
로 할 필요 없다. - 묵시적으로
if (!(o instanceof MyType)
이런 식으로 비교해서 처리하면 null도 한번에 처리된다.
- 보통
-
양질의
equals
메서드 구현 방법==
연산자 이용해서 자기 자신의 참조인지 확인instanceof
연산자 이용해서 입력이 올바른 타입인지 확인- 입력을 올바른 타입으로 형변환 ( 2번이 되면 100% 성공 )
- 입력 객체와 자기 자신의 대응되는 핵심 필드들이 모두 일치하는지 하나씩 검사
equals
를 다 구현했다면 대칭적인가? 추이성이 있는가? 일관적인가 확인- 사실 반사성, null-아님은 문제되는 경우가 거의 없음
equals
를 재정의 할 때hashCode
도 반드시 재정의하자- 너무 복잡하게 해결하려 들지마라
- Object 외의 타입을 매개변수로 받는 equals 메서드는 선언하지 마라
- AutoValue 프레임워크나 IDE에서 제공해주는 것이 사람이 직접 작성하는 것보다 나을 때가 많다.
🔥 꼭 필요한 경우 아니면 equals를 재정의하지 마라! 그래도 굳이 재정의하려면 핵심 필드를 모두 빠짐없이, 다섯 가지 규약을 모두 지켜가며 비교해라