일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- auto.create.topics.enable
- github api
- 람다식
- 프리미티브 타입
- raw 타입
- 항해99
- throwable
- yield
- 함수형 인터페이스
- 합병 정렬
- 제네릭 와일드 카드
- System.err
- 익명 클래스
- System.in
- Study Halle
- System.out
- 정렬
- 접근지시자
- docker
- 자바스터디
- 브릿지 메소드
- 상속
- Switch Expressions
- 바운디드 타입
- junit 5
- annotation processor
- 제네릭 타입
- 로컬 클래스
- 스파르타코딩클럽
- 자바할래
Archives
- Today
- Total
코딩하는 털보
이펙티브 자바, 아이템 10. equals는 일반 규약을 지켜 재정의하라 본문
이펙티브 자바, 아이템 10. equals는 일반 규약을 지켜 재정의하라
equals 메서드는 다음 상황 중 하나에 해당하면 재정의하지 않는 것이 최선
각 인스턴스가 본질적으로 고유하다. ( 주로 값 클래스가 아닌 동작하는 개체를 표현하는 클래스 ex. Thread )
인스턴스의 '논리적 동치성'을 검사할 일이 없다.
상위 클래스에서 재정의한 equals가 하위 클래스에서도 딱 들어맞는다.
클래스가 private이거나 package-private이고 equals 메서드를 호출 할 일이 없다.
그렇다면 equals를 재정의해야 할 때는 언제인가?
인스턴스간 논리적 동치성을 확인해야 하는데, 상위 클래스의 equals가 논리적 동치성을 비교하도록 재정의되지 않았을 때. (주로 값 클래스 ex. String, Integer, ...)
두 값 객체를 비교하는 프로그래머는 물리적으로 같은 객체인지가 아닌 논리적으로 같은 값인지를 확인하고 싶어 할 것이기 때문이다.
equals가 논리적 동치성을 비교할 수 있으면, Map의 키와 Set의 원소로 그 객체를 사용할 수 있다.
- equals의 일반 규약 (x, y, z는 null이 아님.)
- 반사성 : x.equals(x) 는 true
- 대칭성 : x.equals(y)가 true면 y.equals(x) 도 true
- 추이성 : x.equals(y)가 true이고 y.equals(z) 도 true이면 x.equals(z) 도 true이다.
- 일관성 : x.equals(y)를 반본해서 호출하면 항상 true를 반환하거나 항상 false를 반환한다.
- not-null : x.equals(null)은 false이다. (NullPointerException도 허용하지 않는다.)
- 리스코프 치환 원칙
어떤 타입에 있어 중요한 속성이라면 그 하위 타입에서도 마찬가지로 중요하다. 따라서 그 타입의 모든 메서드가 하위 타입에서도 똑같이 잘 작동해야 한다. - 상속했을때 equals 규약 지키기
콘크리트 클래스를 확장해 새로운 값을 추가하면서 equals 규약을 만족시킬 방법은 존재하지 않는다. (대칭성 또는 추이성 위반)
상속 대신 컴포지션을 사용하면 우회할 수 있다. - instanceof를 사용하면 not-null 규약을 쉽게 만족시킬 수 있다.
null instanceof
처럼 instanceof 의 첫 번째 피연산자가 null인 경우 무조건 false를 반환한다.
양질의 equals 메서드 만들기
==
연산자를 사용해 입력이 자기 자신의 참조인지 확인한다.- instanceof 연산자로 입력이 올바른 타입인지 확인한다.
- 입력을 올바른 타입으로 형변환 한다.
- 입력 객체와 자기 자신의 대응되는 '핵심'필드들이 모두 일치하는지 하나씩 검사한다.
핵심 필드를 검사할 때
- float, double이 아닌 기본 타입은
==
연산자로 비교한다. - float, double은
==
연산자가 아닌 Float.compare(), Double.compare() 메서드를 사용한다. - 참조 타입은 각각의 equals 메서드를 사용한다.
- lock 처럼 객체의 논리적 상태와 관련 없는 필드는 비교하면 안 된다.
- float, double이 아닌 기본 타입은
equals를 재정의할 땐 hashCode도 반드시 재정의하자.
너무 복잡하게 해결하려 들지 말자.
Object외의 타입을 매개변수로 받는 equals 메서드는 선언하지 말자. (오버라이딩이 아닌 오버로딩이 되어버린다.)
AutoValue 프레임워크 : equals 및 hashCode를 재정의해주는 오픈소스.
Comments