我们都知道,在Java里面如果想要clone一个对象,可以让类实现Cloneable接口,然后调用其clone方法(最终调用Object的clone方法)。但是这个只是浅拷贝,如果这个类的属性都是私有类型或其包装类,或者是immutable objects(比如String),那clone能够工作很好。 但是一旦其包括mutable objects,比如StringBuffer或者别的对象的引用,那么shallow copy就会导致一个对象的修改会影响另外一个对象。
所以,在这种情况下,我们就需要自己来实现deep copy。最先想到的就是override clone方法,当然你需要在里面遍历所有的mutable属性然后依次clone它们。当然这还不是推荐的做法,在Effective Java "Item 11: Override clone judiciously"中就明确不推荐这种办法,取而代之的是copy constructor or copy factory。
如果不想针对每个对象都写一个自己的copy constructor or copy factory,可以有一些通用的方法,如果性能不是问题的话。
1、利用Java object serialization机制,代码如下,唯一的限制是你的类必须实现Serializable接口,不是什么过分的要求。
- public class ObjectCloner {
- /**
- * Returns a copy of the object, or null if the object cannot be serialized.
- */
- public static Object copy(Object orig) {
- Object obj = null;
- try {
- // Write the object out to a byte array
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- ObjectOutputStream out = new ObjectOutputStream(bos);
- out.writeObject(orig);
- out.flush();
- out.close();
- // Make an input stream from the byte array and read
- // a copy of the object back in.
- ObjectInputStream in = new ObjectInputStream(
- new ByteArrayInputStream(bos.toByteArray()));
- obj = in.readObject();
- } catch (IOException e) {
- e.printStackTrace();
- } catch (ClassNotFoundException cnfe) {
- cnfe.printStackTrace();
- }
- return obj;
- }
- }
详细的介绍请参考:Faster Deep Copies of Java Objects: http://javatechniques.com/blog/faster-deep-copies-of-java-objects/. 里面还提供了上述方法的优化实现。
当然这还有一种变体,除了把对象序列化成一个stream之外,还可以将其序列化成一个xml。利用Xstream这个包可以很容易地实现。
2、一些专门的开源包,连实现Serializable接口都不需要了。
Java generic deep copy: http://www.genericdeepcopy.com/
Java deep-cloning library: http://code.google.com/p/cloning/