핵심 정리: 애매모호한 clone 규약

    // 일반적으로 override 방법은 아니다.
    // 코드 13-1 가변 상태를 참조하지 않는 클래스용 clone 메서드 (79쪽)
    
    @Override
    public PhoneNumber clone() {
        try {
            return (PhoneNumber) super.clone();
        } catch (**CloneNotSupportedException** e) {
            throw new AssertionError();  // 일어날 수 없는 일이다.
        }
    }
    
===
// clone 을 호출할 때는 생성자를 호출하면 안된다. 
// anti pattern 
public class Item implements Cloneable {

  private String name;

  /**
   * 이렇게 구현하면 하위 클래스의 clone()이 깨질 수 있다. p78
   * @return
   */
  @Override
  public Item clone() {
      Item item = new Item();
      item.name = this.name;
      return item;
  }
}

public class SubItem extends Item implements Cloneable {

    private String name;

    @Override
    public SubItem clone() {
        return (SubItem)super.clone();
    }

    public static void main(String[] args) {
        SubItem item = new SubItem();
        SubItem clone = item.clone();

        System.out.println(clone != item);
        System.out.println(clone.getClass() == item.getClass());
        System.out.println(clone.equals(item));
    }
}

핵심 정리: 가변 객체의 clone 구현하는 방법

현실적으로는 생성자를 사용하여 copy 한다.

사용자가 원하는 하위 타입으로 변환이 가능하다.

    // 1. 생성자를 이용한 방법
    public static void main(String[] args) {
        Set<String> hashSet = new HashSet<>();
        hashSet.add("keesun");
        hashSet.add("whiteship");
        System.out.println("HashSet: " + hashSet);

        **Set<String> treeSet** = new TreeSet<>(hashSet);

        System.out.println("TreeSet: " + treeSet);
    
    ====
    
    // 2. copy 생성자 전용 메서드
    public PhoneNUmber(PhoneNUmber phoneNumber){
	    this(phoneNUmber.areaCode, .. )
	  }

완벽 공략