이펙티브 자바 3장에서는 Object 메서드들 정의에 대해 소개하고 있다.
모든 클래스는 일반 규약에 맞춰 재정의 해야하는데 어떻게 재정의 해야하는지 알아본다.
아이템10. equals는 일반 규약을 지켜 재정의하라
equals는 논리적 동치성 검사가 필요하지만 상위 클래스가 재정의하지 않았을 경우 재정의
구글의 AutoValue or IDE 기능 활용
equals구현 방법==연산자로 자기 자신인지 확인 (성능 최적화용)instanceof연산자로 타입 확인 (null도 체크됨)- 올바른 타입으로 형변환
- 대응되는 핵심 필드 비교
equals규약 (어기면 다른 객체에서의 동작을 예상하지 못함)- 반사성 : 객체는 자기 자신과 같음
- 대칭성 : 두 객체가 서로에 대한 동치 여부가 같음
- 추이성 :
x.equals(y),y.equals(z)라면x.equals(z) - 일관성 : 두 불변 객체는 같으면 영원히 같음
- null-아님 : 모든 객체는
null과 같지 않음
equals재정의가 필요없는 경우- 각 인스턴스가 모두 고유한 경우
- 논리적 동치성이 필요 없는 경우
- 상위 클래스에서 재정의했는데 하위에서도 맞는 경우
- 클래스가
private,package-private면서equals호출이 필요없는 경우 - 값이 같은 인스턴스가 2개 이상 만들어지지 않을 경우 (ex. Enum)
- 주의 사항
- 기본 타입
==, 참조 타입equals,float은Float.compare,double은Double.compare으로 필드 비교 - 성능을 위해 다를 가능성이 크거나 비용이 저렴한 필드 우선 비교
- 복잡한 필드를 가진 클래스의 경우 필드의 표준형을 저장
equals재정의할 때, 반드시hashCode도 재정의- 반드시
Object타입을 매개변수로 받아야 함
- 기본 타입
아이템11. equals를 재정의하려거든 hashCode도 재정의하라
hashCode규약- 정보가 변경되지 않는 한, 항상 일관된 값 반환
- 두 객체가
equals로 같다면,hashCode도 같은 값 반환 (가장 중요) equals로 다르다고 해도hashCode도 같을 필요는 없음
hashCode작성 요령int변수result로 선언하고 첫 비교 필드의 해시코드로 초기화- 기본필드
Type.hashCode(f), 참조 타입hashCode재귀 호출,null은 0, 배열은Arrays.hashCode으로 해시코드 계산 - 계산된 해시코드
result할당 result반환
hashCode주의- 핵심필드를 생략하면 안됨
- 생성 규칙을 클라이언트가 의지하지 않도록 자세히 공표하면 안됨
아이템12. toString을 항상 재정의하라
Obejct의 기본 toString은 아무것도 알려주지 않는다.
재정의하여 디버깅하기 쉽도록 한다.
toString권장 사항- 간결하고 사람이 읽기 쉬운 형태의 정보를 제공
- 객체의 모든 주요 정보 반환
- 반환 값의 포맷을 문서화할지 결정 (포맷이 정해지면 변경이 어려움)
- 포맷 명시하거나 안해거나 의도를 명확하게 표현
toString반환 값에 포함된 정보를 얻는 API 명시- 하위 클래스들에 공유해야하는 문자열이 있다면 추상클래스도 재정의
toString재정의가 필요 없는 경우- 정적 유틸리티 클래스
- 열거 타입
- 상위클래스에서 알맞게 재정의
아이템13. clone 재정의는 주의해서 진행하라
clone문제clone메서드는super.clone호출하고 내부 객체 필드는 재귀적으로 호출(스택 오버플로 위험)final한정자를 제거해야할 수 있음- 적절한 동기화 처리 필요
clone대안- 복사 생성자 -> 변환 생성자(conversion constructor)
- 복사 팩터리 -> 변환 팩터리(conversion factory)
아이템 14. Comparable을 구현할지 고려하라
순서가 명확한 값 클래스를 작성한다면 반드시 Comparable 구현
compareTo규약- 두 객체를 바꿔 비교해도 예상한 결과가 나와야 함
- 추이성 →
x.compareTo(y) > 0,y.compareTo(z) > 0라면x.compareTo(z) > 0 - 크기가 같은 객체들끼리 비교하면 항상 같아야 함
compareTo권장<,>연산자 대신 기본 타입 클래스의 정적compare메서드 사용Comparator인터페이스가 제공하는 메서드 사용