Cloneable
은 복제해도 되는 클래스임을 명시하는 용도의 믹스인 인터페이스지만, 아쉽게도 의도한 목적을 제대로 이루지 못했다.
가장 큰 문제는 clone
메서드가 선언된 곳이 Cloneable
이 아닌 Object
이고, 그마저도 protected라는 데 있다.
protected native Object clone() throws CloneNotSupportedException;
Object
명세에 적힌 규약 ❗이 객체의 복사본을 생성해 반환한다. '복사'의 정확한 뜻은 그 객체를 구현한 클래스에 따라 다를 수 있다.
일반적인 의도는 다음과 같다. 어떤 객체 x에 대해 다음 식은 참이다.
x.clone() != x
또한 다음 식도 참이다.
x.clone().getClass() == x.getClass()
하지만 이상의 요구를 반드시 만족해야 하는 것은 아니다.
한편 다음 식도 일반적으로 참이지만, 역시 필수는 아니다.
x.clone().equals(x)
관례상, 이 메서드가 반환하는 객체는 super.clone을 호출해 얻어야 한다.
이 클래스(Object를 제외한) 모든 상위 클래스가 이 관례를 따른다면 다음 식은 참이다.
x.clone().getClass() == x.getClass()
관례상, 반환된 객체와 원본 객체는 독립적이어야 한다.
이를 만족하려면 super.clone으로 얻은 객체의 필드 중 하나 이상을 반환 전에 수정해야 할 수도 있다.
- 가변 상태를 참조하지 않는 클래스용
clone
메서드@Override public Item13 clone() { try { return (Item13) super.clone(); } catch (CloneNotSupportedException e) { throw new RuntimeException(); } }
이 메서드가 동작하게 하려면 Item13의 클래스 선언에 `Cloneable`을 구현해야한다.
만약 구현하지 않는다면 `CloneNotSupportedException`을 던지게 된다.
`clone` 메서드는 사실상 생성자와 같은 효과를 낸다.
즉, `clone`은 원본 객체에 아무런 해를 끼치지 않는 동시에 복제된 객체의 불변식을 보장해야한다.
따라서, 기본 원칙은 '복제 기능은 생성자와 팩터리를 이용하는게 최고'라는 것이다.
단, 배열만은 `clone` 메서드 방식이 가장 깔끔한, 이 규칙의 합당한 예외라 할 수 있다.
(배열은 각 elements도 재귀적으로 `clone`을 해야하기 때문이다.)
참고 자료
Joshua Bloch, 『Effective Java 3/E』, 개앞맵시 옮김, 프로그래밍인사이트(2018)
http://www.kyobobook.co.kr/product/detailViewKor.laf?ejkGb=KOR&mallGb=KOR&barcode=9788966262281&orderClick=LEa&Kc=
'Java' 카테고리의 다른 글
[Effective Java] 아이템 15. 클래스와 맴버의 접근 권한을 최소화하라. (0) | 2022.05.24 |
---|---|
[Effective Java] 아이템 14. Comparable을 구혈할지 고려하라. (0) | 2022.05.24 |
[Effective Java] 아이템 10. equals는 일반 규약을 지켜 재정의하라. (0) | 2022.05.24 |
[Effective Java] 아이템 9. try-finally보다는 try-with-resources를 사용하라. (0) | 2022.05.24 |
[Effective Java] 아이템 7. 다 쓴 객체 참조를 해제하라. (0) | 2022.05.24 |