본문 바로가기
기타/이펙티브 자바

[이펙티브자바] 3. 모든 객체의 공통 메소드

by 창이2 2022. 5. 16.

1. equals는 일반 규약을 지켜 재정의하라.

1. 모든 클래스는 Object를 상속받는데 equals, hashCode, toString, clone, finalize 를 재정의 할 수 있다.

2. equals는 물리적 동치성(메모리 주소가 같은지)이 아니라 논리적 동치성(갖고 있는 값이 같은지 등)을 비교할 때 이다.

3. equals 메소드의 규약을 따라야 한다.

 3.1. 반사성 : x.euqals(x) 는 항상 true - 자기자신은 항상 같다라는 뜻

 3.2. 대칭성 : x.euqals(y) 가 true이면 y.euqals(x) 도 true이다.

 3.3. 추이성 : x.euqals(y) 가 true이고 y.euqals(z) 도 true이면 x.euqals(z)도 true이다.

 3.4. 일관성 : x.euqals(y) 를 반복해서 실행해도 항상 같은 결과를 나타낸다.

 3.5. null 아님 : x.euqals(null) 은 항상 false이다.

 

상속을 통해 추상화의 개념을 가지면서 상위 클래스의 equals와 하위 equals를 동시에 만족하는 규약은 존재할 수 없다. 

 

2. equals는 재정의하려거든 hashCode도 재정의 하라.

1. equals비교에 사용된 정보가 변경되지 않았다면  앱실행동안 해당 객체의 hashCode는 항상 같은 값을 반환해야 한다.

2. equals()가 두 객체를 같다고 판단했다면 두 객체의 hashCode도 같은 값이어야 한다.

3. equals()가 두 객체를 다르다고 판단해도 두 객체의 hashCode는 같을 수 있다.(최대한 다르게 결과를 내야 좋은 해시함수이다.)

4. 해시코드를 구하는 함수는 equals들어가는 field의 해시코드 * 31을 순차적으로 더하여 나타낸다. 

 

3. toString()을 항상 재정의하라.

4. clone 재정의는 주의해서 진행하라.

1. clone함수를 재정의 하기 위해선 Cloneable 인터페이스를 구현해야한다.

2. 상위클래스에서 clone을 재정의 했다면 이를 상속받는 하위클래스에서도 clone을 재정의 해야한다.

더보기
public class Main {

    public static void main(String[] args){

        try {
            CloneParent originalParent = new CloneParent("original parent");

            CloneChild originalChild = new CloneChild("original child");

            CloneParent copiedParent = originalParent.clone();
            CloneChild copiedChild = originalChild.clone();

            System.out.println(originalParent == copiedParent);

            System.out.println(originalChild == copiedChild);

        } catch (CloneNotSupportedException e) {
            throw new RuntimeException(e);
        }

    }

}

class CloneParent implements Cloneable{
    String name;

    public CloneParent(){
    }

    public CloneParent(String name){
        this.name = name;
    }
    @Override
    protected CloneParent clone() throws CloneNotSupportedException {
        return (CloneParent)super.clone();
    }
}

class CloneChild extends CloneParent implements Cloneable{
    String name;

    public CloneChild(){
    }

    public CloneChild(String name){
        super();
        this.name = name;
    }

    //Override 하지 않으면 상위 클래스의 clone이 호출되기 때문에 컴파일 에러 발생
    @Override
    protected CloneChild clone() throws CloneNotSupportedException {
        return (CloneChild)super.clone();
    }
}

 

3. 불변 클래스에는 clone 메서드를 제공하지 말아라.(불필요한 복사)

4. 상속용 클래스는 Cloneable를 구현하지 말거나 clone 을 동작하지 않도록 해야한다.

5. clone을 구현할때는 Thread Safety도 함께 고려해야 한다.

 

댓글