book review/Effective java

[Effective Java] Item 13. clone 재정의는 주의해서 진행하라

dobidugi 2024. 7. 1. 07:45

Cloneable 인터페이스

Java에는 Cloneable이라는 믹스인 인터페이스가 존재가 있다.

해당 인터페이스를 찾아보면 아무것도 없는걸 볼 수 있는데,  해당 인터페이스의 용도는 Cloneable 인터페이스로 구현된 클래스에서 clone메서드를 호출할때  안전하게 Object.clone()메서드가 해당 클래스의 필드를 복사 할 수 있음을 나타낸다.

만약 Cloneable을 사용하지않는 클래스에서 clone을 호출하게된다면 CloneNotSupportException을 발생시킨다.

 

clone 메소드의 규약

clone 메서드가 usper.clone이 아닌, 생성자를 호출해 얻은 인스턴스를 반환해도 컴파일러는 불평하지 않음

clone을 재정의한 클래스가 final이라면 걱정해야 할 하위 클래스가 없으니 아래 관례는 무시해도 된다.

x.clone != x // 이 식은 참이다
x.clone().getClass == x.getClass() // 이 식은 참이지만 반드시 만족해야하는건 아님
// 관례상 이 메소드가 반환하는 객체는 super.clon을 호출해 얻어야함
x.clone().getClass().equals(x) // 이 식은 참이지만 필수는 아님
x.clone().getClass() == x.getClass()
// 관례상 반환된 객체와 원본 객체는 독립적이여야함
// 이를 만족하려면 super.clone으로 얻은 객체의 필드 중 하나 이상을 반환 전에 수정해야할 수 있음

 

재 정의시 문제점

 

가변 상태를 참조하는 클래스용 clone 메서드 에서의 문제

@Override public Stack clone() {
	private Object[] elements;
    
   	@Override public Stack clone(){
        try {
        Stack result = (Stack) super.clone();
            result.elements = elements.clone();
            return result;
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        }
   }

}

이런식으로 복사하지않으면 elements의 참조 주소를 복사하게되며 이렇게될 경우 원본값이 변경되면 복사본값도 변경될 수 있기때문에 조심 해야함

 

HashTable 복제

/* TODO */

 

마무리

사실상 clone 메서드는 생성자와 같은 효과를내며 원본 객체에 아무런 해를 끼치지않는동시에 복제된 객체의 불변을 보장해야함