이 인터페이스는 Object 클래스의 protected 메소드인 clone의 행동 방식을 규정한다. 만약, clone 메소드가 호출된 객체가 Cloneable 타입이라면, Object.clone 메소드는 이 객체의 모든 필드를 그대로 복사한 복제본을 리턴한다. 하지만 Cloneable 타입이 아니라면 CloneNotSupportedException을 던진다.
java.lang.Object.clone의 명세(Specification)
보통 모든 객체 x에 대하여, 다음 식
x.clone() != x는 true 이고, 또 다음 식
x.clone().getClass() == x.getClass()
도 true이지만 반드시 지켜야 할 사항은 아니다. 또 다음 식
x.clone().equals(x)
도 true이지만 반드시 지켜야 할 사항은 아니다. 어떤 객체를 복제할 때 보통 이 객체 클래스의 새로운 인스턴스는 반드시 생성해야 하지만, 내부 데이터 구조도 역시 복제해야 할지도 모른다. 이 메소드는 어떤 생성자도 호출하면 안 된다.
일반적인 Class의 clone() method
- field가 모두 기본형 타입일 경우
try {
return super.clone();
} catch(CloneNotSupportedException e) {
throw new Error("Assertion failuer");
}
}
어떤 객체가 가변 객체를 참조하는 필드를 갖고 있는 Stack클래스를 생각해 보자.
Stack 클래스의 clone 메소드가 올바르게 동작하려면, 원본 객체가 내부적으로 포함하고 있는 객체까지도 복제해주어야 한다.
그리고 그렇게 하는 가장 쉬운 방법은, elements 배열에 대해 재귀적으로 clone 메소드를 호출하는 것이다.
Cloneable을 implements 하는 클래스의 서브 클래스에서는 clone 메소드를 잘 구현해야한다.
객체를 복제하는 다른 방법을 제공하거나, 또는 복제할 수 없도록 하는 것이 좋다.
예를 들어, 불변 클래스의 객체 복제를 지원하는 것은 바람직하지 않다. 사실상 복제본이 원본과 같기 때문이다.
객체를 복제하는 좋은 방법은 복제 생성자나 복제 팩토리 메소드를 제공하는 것이다. 복제 생성자는 그냥 생성자로써, 그 생성자를 포함하는 클래스를 타입으로 하는
인자를 하나만 갖는다.
public Yum(Yum yum);
복제 팩토리는 복제 생성자와 유사한 static 팩토리 메소드로 다음과 같다.
public static Yum newInstance(Yum yum);
복제 생성자와 복제 팩토리 메소드를 사용하는 방법은 Cloneable 과 Clone을 사용하는 것에 대해 많은 장점을 갖고 있다.
'backend > Java' 카테고리의 다른 글
throw new UnsupportedOperationException() (4) | 2009.10.30 |
---|---|
[Effective Java] 23. 새로 작성하는 코드에서는 원천(raw) 타입을 사용하지 말자. (0) | 2009.10.30 |
[Effective Java] 19. 타입을 정의할 때만 인터페이스를 사용하자. (2) | 2009.10.27 |
[Effective Java] 15. 가변성을 최소화하자. (2) | 2009.10.19 |
[Effective Java] 9. equals 메소드를 오버라이드 할 땐 hashCode 메소드도 항상 오버라이드 하자. (0) | 2009.09.28 |
[Effective Java] 8. equals 메소드를 오버라이딩 할 때는 보편적 계약을 따르자. (4) | 2009.09.24 |
[Effective Java] 5. 불필요한 객체 생성을 피하자 (4) | 2009.09.23 |
[Effective Java] 4. private 생성자를 사용해서 인스턴스 생성을 못하게 하자 (0) | 2009.09.17 |