Class Java

// : appendixa:CheckCloneable.java
// Checking to see if a reference can be cloned.
// From 'Thinking in Java, 3rd ed.' (c) Bruce Eckel 2002
// www.BruceEckel.com. See copyright notice in CopyRight.txt.
// Can't clone this because it doesn't override clone():
class Ordinary {
}
// Overrides clone, but doesn't implement Cloneable:
class WrongClone extends Ordinary {
  public Object clone() throws CloneNotSupportedException {
    return super.clone(); // Throws exception
  }
}
// Does all the right things for cloning:
class IsCloneable extends Ordinary implements Cloneable {
  public Object clone() throws CloneNotSupportedException {
    return super.clone();
  }
}
// Turn off cloning by throwing the exception:
class NoMore extends IsCloneable {
  public Object clone() throws CloneNotSupportedException {
    throw new CloneNotSupportedException();
  }
}
class TryMore extends NoMore {
  public Object clone() throws CloneNotSupportedException {
    // Calls NoMore.clone(), throws exception:
    return super.clone();
  }
}
class BackOn extends NoMore {
  private BackOn duplicate(BackOn b) {
    // Somehow make a copy of b and return that copy.
    // This is a dummy copy, just to make the point:
    return new BackOn();
  }
  public Object clone() {
    // Doesn't call NoMore.clone():
    return duplicate(this);
  }
}
// You can't inherit from this, so you can't override
// the clone method as you can in BackOn:
final class ReallyNoMore extends NoMore {
}
public class CheckCloneable {
  public static Ordinary tryToClone(Ordinary ord) {
    String id = ord.getClass().getName();
    System.out.println("Attempting " + id);
    Ordinary x = null;
    if (ord instanceof Cloneable) {
      try {
        x = (Ordinary) ((IsCloneable) ord).clone();
        System.out.println("Cloned " + id);
      } catch (CloneNotSupportedException e) {
        System.err.println("Could not clone " + id);
      }
    } else {
      System.out.println("Doesn't implement Cloneable");
    }
    return x;
  }
  public static void main(String[] args) {
    // Upcasting:
    Ordinary[] ord = { new IsCloneable(), new WrongClone(), new NoMore(),
        new TryMore(), new BackOn(), new ReallyNoMore(), };
    Ordinary x = new Ordinary();
    // This won't compile; clone() is protected in Object:
    //! x = (Ordinary)x.clone();
    // Checks first to see if a class implements Cloneable:
    for (int i = 0; i < ord.length; i++)
      tryToClone(ord[i]);
  }
} ///:~