///
Search
💡

item 13. Clone 재정의는 주의해서 진행하라 Override clone judiciously

clone()? 어디서 쓰는 것인지?

Cloneable은 복제해도 되는 클래스임을 명시하는 용도의 인터페이스다. 하지만 아쉽게도 목적 달성엔 실패했는데, clone() 메서드가 선언된 곳이 Object라는 점이기 때문이다. 특이하게도 Clonable 자체엔 메서드가 없고, Cloneable을 구현하고 Object의 clone()메서드를 호출하면 값을 복사한 객체를, 그렇지 않으면 CloneNotSupportedException을 반환한다. (인터페이스가 상위 객체의 메서드의 행위를 변경하므로, 좋은 방식은 아니다)
명세엔 없지만 실무에선 Cloneable을 구현한 클래스는 clone 메서드를 public으로 제공한다.

cloneable의 주의점 및 문제점

1.
A 클래스의 clone을 호출 할 때 상위클래스에서 정의한 clone이 호출 된다면, A클래스가 아닌 상위클래스가 반환되게 된다. 이를 처리하기 위해 공변 반환 타이핑(재정의한 메서드의 반환타입은 상위 클래스의 메서드가 반환하는 타입의 하위 타입일 수 있다.)을 이용할 수 있다.
2.
super.clone()을 호출 하는 방식의 clone은 동일 참조의 필드를 전달해 오류가 생길 수 있다. 이를 막기 위해 재귀적으로 필드에 대한 clone()을 호출할 필요가 있다.
3.
CloneNotSupportedException을 체크드 예외로 던짐으로써 예외처리를 반드시 하도록 명시한다. Cloneable을 구현해 발생할 가능성이 없는 코드에서도!
4.
생성자와 동일한 역할을 하기 때문에 생성자의 역할을 모호하게 한다.

사용하지 말자

Cloneable은 다양한 문제를 수반하므로, 새로운 인터페이스를 만들 때 Cloneable을 확장해서는 안 되고, 새로운 클래스도 이를 구현해서는 안 된다. final 클래스라면 구현해도 크게 위험하지 않지만, 성능 최적화 관점에서 문제가 없을 때 만 드물게 허용해야한다.
기본 원칙은 생성자와 팩터리를 이용하는 것이다.
배열만큼은 clone 메서드 방식이 적합하다. 사용하지 말자는 규칙에 예외라고 할 수 있다.

용어정리

한글명
영어명
결함
flaw
~~에도 불구하고
Despite
적절한
appropriate
공변 반환 타이핑
covariant return typing