// file: Copier.java // author: Robert Keller // purpose: To give a general purpose copy method that will clone if possible, // otherwise just return its argument. import java.lang.reflect.*; // to use getMethod() and invoke() /** * Copier exists to provide one static method, maybeClone which makes a clone * of its argument, or returns the argument itself if not. */ class Copier { static Class[] noArgs = new Class[0]; // a Class array of size 0 static Object[] args = new Object[0]; // an Object array of size 0 /** * Copies an Object, as far as that is possible. * If the Object implements the Cloneable interface, then returns a Clone of * the Object. Otherwise returns the Object itself. */ static Object maybeClone(Object ob) { // One cannot apply clone() to any class unless it implements the Cloneable // interface, which class Object does not. (It does so as a protected // method, but we need a public method.) // // The only means I could find of implementing a method of the desired // generality is to use the "reflection" ideas in java.lang.reflect. // These allow one to determine whether there is a method with a specific // name and arguments of a specific type, to get such a method if there is, // and to invoke the method on actual arguments. // In our case we are interested in whether the clone() // method exists with no arguments. if( ob instanceof Cloneable ) { try { // System.out.println(ob + " is instanceof Cloneable"); // If Cloneable, clone it. return ob.getClass().getMethod("clone", noArgs).invoke(ob, args); } catch( Exception e) { // System.out.println(ob + " is not instanceof Cloneable"); } } return ob; // If Otherwise just return the argument. } }