아이템 13 : clone 재정의는 주의해서 진행하라
Cloneable은 복제해도 되는 클래스임을 명시하는 용도의 믹스인 인터페이스지만, 아쉽게도 의도한 목적을 제대로 이루지 못했다. 가장 큰 문제는 clone 메서드가 선언된 곳이 Cloneable이 아닌 Object이고, 그마저도 protected라는 데 있다. 그래서 Cloneable을 구현하는 것만으로는 외부 객체에서 clone 메서드를 호출할 수 없다.
실무에서 Cloneable을 구현한 클래스는 clone 메서드를 public으로 제공하며, 사용자는 당연히 복제가 제대로 이루어지리라 기대한다. 이 기대를 만족시키려면 그 클래스와 모든 상위 클래스는 복잡하고, 강제할 수 없고, 허술하게 기술된 프로토콜을 지켜야만 하는데, 그 결과로 깨지기 쉽고, 위험하고, 모순적인 메커니즘이 탄생한다. 생성자를 호출하지 않고도 객체를 생성할 수 있게 되는 것이다.
clone 메서드는 사실상 생성자와 같은 효과를 낸다. 즉, clone은 원본 객체에 아무런 해를 끼치지 않는 동시에 복제된 객체의 불변식을 보장해야한다.
핵심 정리
Cloneable이 몰고 온 모든 문제를 되짚어봤을 때, 새로운 인터페이스를 만들 때는 절대 Cloneable을 확장해서는 안 되며, 새로운 클래스도 이를 구현해서는 안 된다. final 클래스라면 Cloneable을 구현해도 위험이 크지 않지만, 성능 최적화 관점에서 검토한 후 별다른 문제가 없을 때만 드물게 허용해야 한다. 기본 원칙은 '복제 기능은 생성자와 팩터리를 이용하는게 최고'라는 것이다. 단, 예외적으로 배열만은 clone 메서드 방식이 가장 깔끔하다.
'언어 > JAVA' 카테고리의 다른 글
[Effective Java] 클래스와 멤버의 접근 권한을 최소화하라 (0) | 2020.03.16 |
---|---|
[Effective Java] Comparable을 구현할지 고려하라 (0) | 2020.03.15 |
[Effective Java] toString을 항상 재정의하라 (0) | 2020.03.14 |
[Effective Java] equals를 재정의하거든 hashCode도 재정의하라 (0) | 2020.03.14 |
[Effective Java] equals는 일반 규약을 지켜 재정의하라 (0) | 2020.03.13 |