kok202
[2019.03.09] 이펙티브 자바 3판 (3장 : 공통 메소드)

2019. 3. 10. 02:11[공부] 독서/이펙티브 자바 3판

공통 메소드

  • equals
  • hashCode
  • toString
  • finalize

특정 메소드의 호출이 금지 되게 하고 싶으면 오버라이딩하고 throw new AssertionError(); 를 넣어놔라
꼭 필요한게 아니면 재정의 하지말라

공통메소드를 재정의 할 때는 다음 규약을 지켜야한다.

 

 

 

equals

equals은 논리적 동일성을 판단하는 메소드다.

상위 클래스에서 재정의한 equals 는 하위 클래스의 equals에도 상속된다.

equals를 재정의하면 hashcode도 재정의 해야한다.

equals 메소드는 동치 관계여야한다.

  • 반사성 : x.equals(x) = true
  • 대칭성 : x.equals(y) = true => y.equals(x) = true
  • 연쇄성 : x.equals(y) y.equals(z) = true => x.equals(z) = true
  • null아님 : x.equals(null) => false

위배되는 예시는 책을 참고

저자가 제시하는 equals 메소드의 템플릿

@Override
public boolean equals(Object object) {
    if (this == object)
        return true;
    if (!(object instanceof MyType))
        return false;
    MyType myObject = (MyType) object;
    //...
}

매개변수는 Object object 여야한다.

그렇지 않으면 그냥 오버로딩 한 거다.

equals 안에서 비교할 때 float, double 변수는 Float.compare, Double.compare을 이용하여 비교하라

float과 double은 NaN, -0.0f 등이 존재한다.

Float.equals, Double.equasl 는 오토박싱이 뒤따를 수 있으니 조심해야한다.

 

 

hashCode

hashCode는 hashMap 같은 걸 쓸 때 hash값을 계산하기 위하여 쓰는 함수다.

equals의 결과 값이 같다면 두 객체의 hashCode 값도 같아야한다.

hashCode 작성 요령

@Override
public int hashCode() {
    int result = Integer.hashCode(A);
    result = 31 * result + Integer.hashCode(B);
    result = 31 * result + Integer.hashCode(C);
    return result;
}

간결하긴한데 조금 느리다.

@Override
public int hashCode() {
    return Object.hash(A, B, C);
}

 

 

 

toString

가능하면 항상 재정의하라

주요 정보를 반환하라

 

 

 

Cloneable

Cloneable 인터페이스 재정의는 주의하라

public class Point implements Cloneable {
    private int x;
    private int y;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

가능하면 쓰지마라.

제대로 동작하는 clone을 구현하기란 참 어려운 일이다.

clone 된 객체의 변경은 원본에 아무런 변경을 가해서는 안된다.

clone 된 객체는 원본의 객체와 동일해야한다.

어떤 멤버 변수가 참조형 데이터를 바라보고 있다면 여기서부터 망한다.

상위 클래스가 Clonable 하게 두지마라

하위 클래스도 전부 clone을 재정의해야한다.

 

Comparable 인터페이스를 구현할 것인지 말 것인지 고려해라.

Comparable 인터페이스의 compareTo 메소드 : 단순 동치성 비교 + 순서 비교

sort가 필요한 클래스에서 어떤 변수를 기준으로 sorting 할 것인지 정의 가능하다.

public interface Comparable < T > {
    int compareTo(T t);
}
public class Circle implements Comparable < Circle > {
    private int radius;

    @Override
    public int compareTo(Circle cmpCircle) {
        return Integer.compare(this.radius, cmpCircle.radius);
    }
}

return 값이 음수 : 왼쪽이 크다.

return 값이 제로 : 같다.

return 값이 양수 : 오른쪽이 크다.

 

두 객체의 compareTo 값은 다음을 보장해야한다.

x.compareTo(y) = -y.compareTo(x)
x.compareTo(y) > 0, y.compareTo(z) > 0 => x.compareTo(z) > 0
x.compareTo(y) = 0, y.compareTo(z) = 0 => x.compareTo(z) = 0

compare 할 때 두개의 변수를 뺀 값을 return 하는 코드가 있는데 가능하면 이렇게 사용하는 방법은 피해라. 오버플로우가 발생할 경우 대소 비교가 잘못된다. 이외에 다른 문제가 있을 수 있으니 피하는 것이 좋다.