容器类(ArrayList等)提供的clone方法只是浅copy(shallow copy),即重新生成并保存了指向目标类的一系列指针。要实现深copy,必须通过新容器对象的添加方法添加目标对象的clone。如:list_x.add(obj.clone())。即目标对象应很好地实现clone方法。但目前,传统的clone方法设计模式在泛型编程时会出现问题:
public class Foo<T extends Cloneable> { T obj; public Object clone() { obj.clone(); } }这段代码无法通过编译:obj继承有Object的clone方法,但不能从外部调用;Cloneable是个空的、标志接口,没有声明clone方法。所以,obj没有公开的clone方法供调用。
一个设计策略是由Cloneable接口派生一个接口,其中声明clone方法,然后泛型约束到该接口。如下列代码所示:
public interface IClone implements Cloneable { public Object clone(); } public class Foo<T extends IClone> { T obj; public Object clone() { obj.clone(); } }
一个更加健壮的clone方法实现是通过反射技术,如下列代码:
public MyClass<T> clone( ) throws CloneNotSupportedException { MyClass<T> clon = null; try { clon = (MyClass<T>)super.clone(); } catch (CloneNotSupportedException e) { throw new InternalError(); } try { Class<?> clzz = this.field_a.getClass(); Method meth = clzz.getMethod("clone", new Class[0]); Object dupl = meth.invoke(this.field_a, new Object[0]); clon.field_a = (T)dupl; } catch (Exception e) { throw new CloneNotSupportedException (e.toString()); } }
实际编程中,很难事先设计周全,经常遇到涉及类没有完整实现clone方法的情况,此时,可使用下列通过序列化技术实现的深copy方法(注意:此方法要求被clone的对象实现java.io.Serializable接口):
import java.io.*; import java.util.*; /** This class is a tool to clone an object deeply. */ public class Cloner { private Cloner() { } /** This method returns a deep copy of an object. @param src the source object to be cloned @return a deep copy of src */ public static Object clone(Object src) throws Exception { ObjectOutputStream oos = null; ObjectInputStream ois = null; try { ByteArrayOutputStream bos = new ByteArrayOutputStream(); oos = new ObjectOutputStream(bos); // serializing and passing the object oos.writeObject(src); oos.flush(); ByteArrayInputStream bin = new ByteArrayInputStream(bos.toByteArray()); ois = new ObjectInputStream(bin); // returning the new object return ois.readObject(); } catch (Exception e) { System.out.println("Exception in Cloner: " + e); throw(e); } finally { oos.close(); ois.close(); } } }
没有评论:
发表评论