Java:深度克隆/复制实例的推荐解决方案

Gui*_*ume 173 java clone

我想知道是否有推荐的方法在java中进行深度克隆/复制实例.

我有三个解决方案,但我可以错过一些,我想得到你的意见

编辑:包括Bohzo的提议和改进问题:它更多的是深度克隆而不是浅层克隆.

自己做:

在属性之后通过hand属性编写克隆代码并检查是否也克隆了可变实例.
亲:
- 控制将要执行的操作
- 快速执行
缺点:
- 编写和维护繁琐
- 容易出错(复制/粘贴失败,缺少属性,重新分配的可变属性)

使用反射:

使用您自己的反射工具或外部帮助程序(如jakarta common-beans),可以轻松编写一个通用的复制方法,该方法可以在一行中完成工作.
亲:
- 易于编写
- 没有维护
缺点:
- 对发生的事情的控制较少
- 如果反射工具也没有克隆子对象,则容易出现可变对象的错误
- 执行速度较慢

使用克隆框架:

使用为您执行此操作的框架,例如:
commons-lang SerializationUtils
Java Deep Cloning Library
Dozer
Kryo

亲:
- 与反思一样
- 更多地控制将要克隆的内容.
缺点:
- 即使在层次结束时,每个可变实例都被完全克隆
- 执行起来可能非常慢

使用字节码检测在运行时编写克隆

javassit,BCELcglib可能用于生成专用克隆器,只需单手写入.为此目的,有人知道使用这些工具之一的lib吗?

我错过了什么?
你会推荐哪一个?

谢谢.

Boz*_*zho 151

对于深度克隆(克隆整个对象层次结构):

  • commons-lang SerializationUtils - 使用序列化 - 如果所有类都在您的控件中,您可以强制实现Serializable.

  • Java深度克隆库 - 使用反射 - 在您想要克隆的类或对象超出您的控制(第三方库)并且您无法实现它们的情况下Serializable,或者在您不想实现的情况下Serializable.

对于浅层克隆(克隆只有第一级属性):

我故意省略了"自己动手"选项 - 上面的API可以很好地控制要克隆的内容和不克隆的内容(例如使用transient或者String[] ignoreProperties),因此重新发明轮子不是首选.


LeW*_*ody 35

Joshua Bloch的书中有一整章题为"第10项:明智地克服克隆",其中他解释了为什么在大多数情况下克服克隆是一个坏主意,因为它的Java规范产生了许多问题.

他提供了一些选择:

Java中的所有集合类都支持复制构造函数(例如new ArrayList(l);)

  • 同意。在我的项目中,我定义了一个包含“getCopy()”方法的“Copyable”接口。只需手动使用原型模式即可。 (2认同)
  • @LWoodyiii这个`newInstance()`方法和`Yum`构造函数会做深拷贝还是浅拷贝? (2认同)

And*_*hev 9

从版本2.07开始,Kryo支持浅/深克隆:

Kryo kryo = new Kryo();
SomeClass someObject = ...
SomeClass copy1 = kryo.copy(someObject);
SomeClass copy2 = kryo.copyShallow(someObject);
Run Code Online (Sandbox Code Playgroud)

Kryo很快,在他们的页面上你可以找到一个在生产中使用它的公司列表.


小智 5

在内存中使用XStream toXML/fromXML.非常快,已经存在了很长时间,并且变得越来越强大.对象不需要是可序列化的,并且您没有使用反射(尽管XStream可以).XStream可以识别指向同一对象的变量,而不会意外地生成实例的两个完整副本.这些年来,很多细节都被敲定了.我已经使用了很多年了,这是一个很好的选择.它就像你想象的那样容易使用.

new XStream().toXML(myObj)
Run Code Online (Sandbox Code Playgroud)

要么

new XStream().fromXML(myXML)
Run Code Online (Sandbox Code Playgroud)

要克隆,

new XStream().fromXML(new XStream().toXML(myObj))
Run Code Online (Sandbox Code Playgroud)

更简洁:

XStream x = new XStream();
Object myClone = x.fromXML(x.toXML(myObj));
Run Code Online (Sandbox Code Playgroud)