[Item13] clone 재정의는 주의해서 진행하라.

윤들윤들·2020년 12월 27일
0

EffectiveJava

목록 보기
13/17
post-thumbnail

Cloneable 는 복제해도 되는 클래스라는것을 명시하는 용도의 인터페이스 이지만, clone메서드가 선언된 곳이 Cloneable 클래스가 아닌 Object 클래스이다
또한 clone 메서드는 protected로 되어있다. 그래서 외부 객체에서 clone 메서드를 호출할 수 없다. ( 리플렉션을 사용하면되지만 반드시 성공하는 것은 아니다 )

// 실제 Object 클래스 안에있는 clone의 코드
protected native Object clone() throws CloneNotSupportedException;

하지만, 이런 문제가 있더라도 실제로 Cloneable 방식을 널리 사용되고 있기 때문에 알아두면 좋습니다.

Item13에서는 clone 메서드를 구현하는 방법과 언제 그렇게 사용하는지 설명이 되어있다.

실제로 메서드 하나 없는 Cloneable Interface는 무슨 일을 하기 위해 있는걸까

// 실제 Cloneable interface
public interface Cloneable {
}

Cloneable interface는 Object의 protected메서드인 clone메서드의 동작 방식을 결정한다.

Cloneable을 구현한 클래스의 인스턴스에서 clone를 호출하게 된다면 해당 객체의 필드들을 하나하나 복사한 객체를 반환한다. 만약 그렇지 않은 클래스의 인스턴스에서 호출하면 CloneNotSupportedException을 던진다(Object의 기본코드에 명시).

대략적으로 구현해보면 다음과 같이 표현할 수 있다 .

package items;

public class CloneExample {

    public static void main(String[] args) throws CloneNotSupportedException {
        A a = new A("YundleYundle" , 28);
        A cloneA = a.clone();

        System.out.println("(a == cloneA) = " + (a == cloneA));

        B b = new B("YundleYundle" , 28);
        B cloneB = b.clone();

        System.out.println("(a == cloneB) = " + (b == cloneB));
    }
}


class A implements Cloneable {

    private String name;
    private int age;

    public A(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public A clone() throws CloneNotSupportedException {
        A clone = (A)super.clone();
        return clone;
    }
}

class B {

    private String name;
    private int age;

    public B(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public B clone() throws CloneNotSupportedException {
        B clone = (B)super.clone();
        return clone;
    }
}

인터페이스를 구현한다는 것은 해당 클래스가 그 인터페이스에서 정의한 메서드 또는 기능을 제공한다고 선언하는 행위이지만 , Cloneable 경우에는 상위클래스(Object)에서 정의된 protected 메서드의 동작 방식을 변경한 것이다.

Item13의 Cloneable 같은경우는 글로 설명하기가 너무 힘들것같다...

직접 책을 읽어보는것을 추천하며 마지막으로 정리하면 다음과 같다 .

새로운 Interface를 만들때는 절대 Cloneable를 확장해서는 안된다.
새로운 클래스 또한 Cloneable 를 구현해서는 안된다.
기본 원칙은 복제 기능은 생성자와 팩터리를 이용하는것이 최고다.
clone메서드 방식이 가장 깔끔한 예외라고 할 수 있다.

profile
Front&BaackEnd를 재미있게 공부하고싶은 개발자 YundleYundle

0개의 댓글