实现深度对象复制函数有点困难。您采取什么步骤来确保原始对象和克隆对象没有共享引用?
当前回答
您可以使用具有简单API的库,并使用反射执行相对快速的克隆(应该比序列化方法快)。
Cloner cloner = new Cloner();
MyClass clone = cloner.deepClone(o);
// clone is a deep-clone of o
其他回答
一些人提到了使用或重写Object.clone()。不要这样做。Object.clone()存在一些主要问题,在大多数情况下不鼓励使用它。请参见Joshua Bloch的“Effective Java”中的第11项,以获得完整的答案。我相信您可以安全地在基本类型数组上使用Object.clone(),但除此之外,您还需要明智地正确使用和重写clone。
依赖于序列化(XML或其他方式)的方案是拙劣的。
这个问题没有简单的答案。如果你想要深度复制一个对象,你必须遍历对象图,并通过对象的复制构造函数或静态工厂方法显式复制每个子对象,然后再深度复制子对象。不需要复制不可变对象(例如字符串)。顺便说一句,出于这个原因,您应该支持不可变性。
适用于Spring框架用户。使用类org.springframework.util.SerializationUtils:
@SuppressWarnings("unchecked")
public static <T extends Serializable> T clone(T object) {
return (T) SerializationUtils.deserialize(SerializationUtils.serialize(object));
}
您可以使用具有简单API的库,并使用反射执行相对快速的克隆(应该比序列化方法快)。
Cloner cloner = new Cloner();
MyClass clone = cloner.deepClone(o);
// clone is a deep-clone of o
XStream在这种情况下非常有用。这是一个简单的代码来做克隆
private static final XStream XSTREAM = new XStream();
...
Object newObject = XSTREAM.fromXML(XSTREAM.toXML(obj));
一个安全的方法是序列化对象,然后反序列化。这确保了所有内容都是全新的参考。
这里有一篇关于如何有效地做到这一点的文章。
注意:类可以重写序列化,这样就不会创建新的实例,例如单例。当然,如果你的类不是序列化的,这也行不通。
推荐文章
- codestyle;把javadoc放在注释之前还是之后?
- 如何在Spring中定义List bean ?
- 将Set<T>转换为List<T>的最简洁的方法
- 在JavaScript中,什么相当于Java的Thread.sleep() ?
- 使用Java重命名文件
- URL从Java中的类路径加载资源
- .toArray(new MyClass[0]) or .toArray(new MyClass[myList.size()])?
- Hibernate中不同的保存方法之间有什么区别?
- Java 8流和数组操作
- Java Regex捕获组
- Openssl不被视为内部或外部命令
- 如何添加自定义方法到Spring Data JPA
- 如何在Ubuntu中设置Java环境路径
- 无法执行dex:在Eclipse中超过GC开销限制
- 有人能解释一下JPA和Hibernate中的mappedBy吗?