Class Java

// : appendixa:CopyConstructor.java
// A constructor for copying an object of the same
// type, as an attempt to create a local copy.
// From 'Thinking in Java, 3rd ed.' (c) Bruce Eckel 2002
// www.BruceEckel.com. See copyright notice in CopyRight.txt.
import java.lang.reflect.Constructor;
class FruitQualities {
  private int weight;
  private int color;
  private int firmness;
  private int ripeness;
  private int smell;
  // etc.
  public FruitQualities() { // Default constructor
    // Do something meaningful...
  }
  // Other constructors:
  // ...
  // Copy constructor:
  public FruitQualities(FruitQualities f) {
    weight = f.weight;
    color = f.color;
    firmness = f.firmness;
    ripeness = f.ripeness;
    smell = f.smell;
    // etc.
  }
}
class Seed {
  // Members...
  public Seed() { /* Default constructor */
  }
  public Seed(Seed s) { /* Copy constructor */
  }
}
class Fruit {
  private FruitQualities fq;
  private int seeds;
  private Seed[] s;
  public Fruit(FruitQualities q, int seedCount) {
    fq = q;
    seeds = seedCount;
    s = new Seed[seeds];
    for (int i = 0; i < seeds; i++)
      s[i] = new Seed();
  }
  // Other constructors:
  // ...
  // Copy constructor:
  public Fruit(Fruit f) {
    fq = new FruitQualities(f.fq);
    seeds = f.seeds;
    s = new Seed[seeds];
    // Call all Seed copy-constructors:
    for (int i = 0; i < seeds; i++)
      s[i] = new Seed(f.s[i]);
    // Other copy-construction activities...
  }
  // To allow derived constructors (or other
  // methods) to put in different qualities:
  protected void addQualities(FruitQualities q) {
    fq = q;
  }
  protected FruitQualities getQualities() {
    return fq;
  }
}
class Tomato extends Fruit {
  public Tomato() {
    super(new FruitQualities(), 100);
  }
  public Tomato(Tomato t) { // Copy-constructor
    super(t); // Upcast for base copy-constructor
    // Other copy-construction activities...
  }
}
class ZebraQualities extends FruitQualities {
  private int stripedness;
  public ZebraQualities() { // Default constructor
    super();
    // do something meaningful...
  }
  public ZebraQualities(ZebraQualities z) {
    super(z);
    stripedness = z.stripedness;
  }
}
class GreenZebra extends Tomato {
  public GreenZebra() {
    addQualities(new ZebraQualities());
  }
  public GreenZebra(GreenZebra g) {
    super(g); // Calls Tomato(Tomato)
    // Restore the right qualities:
    addQualities(new ZebraQualities());
  }
  public void evaluate() {
    ZebraQualities zq = (ZebraQualities) getQualities();
    // Do something with the qualities
    // ...
  }
}
public class CopyConstructor {
  public static void ripen(Tomato t) {
    // Use the "copy constructor":
    t = new Tomato(t);
    System.out.println("In ripen, t is a " + t.getClass().getName());
  }
  public static void slice(Fruit f) {
    f = new Fruit(f); // Hmmm... will this work?
    System.out.println("In slice, f is a " + f.getClass().getName());
  }
  public static void ripen2(Tomato t) {
    try {
      Class c = t.getClass();
      // Use the "copy constructor":
      Constructor ct = c.getConstructor(new Class[] { c });
      Object obj = ct.newInstance(new Object[] { t });
      System.out.println("In ripen2, t is a " + obj.getClass().getName());
    } catch (Exception e) {
      System.out.println(e);
    }
  }
  public static void slice2(Fruit f) {
    try {
      Class c = f.getClass();
      Constructor ct = c.getConstructor(new Class[] { c });
      Object obj = ct.newInstance(new Object[] { f });
      System.out.println("In slice2, f is a " + obj.getClass().getName());
    } catch (Exception e) {
      System.out.println(e);
    }
  }
  public static void main(String[] args) {
    Tomato tomato = new Tomato();
    ripen(tomato); // OK
    slice(tomato); // OOPS!
    ripen2(tomato); // OK
    slice2(tomato); // OK
    GreenZebra g = new GreenZebra();
    ripen(g); // OOPS!
    slice(g); // OOPS!
    ripen2(g); // OK
    slice2(g); // OK
    g.evaluate();
  }
} ///:~