克隆()与复制构造函数 – 这是在java中推荐
克隆方法vs在java复制构造函数。 哪一个是正确的解决scheme。 在哪里使用每个案例?
克隆被破坏,所以不要使用它。
Object类的CLONE方法是一种有点神奇的方法,它不会执行任何纯Java方法:它会生成一个相同的对象副本。 自从Java编译器*的beta版本发布以来,它已经存在于原始的Object超类中; 和所有古代的魔法一样,它需要适当的咒语来防止这个咒语意外的回火
优选一种复制对象的方法
Foo copyFoo (Foo foo){ Foo f = new Foo(); //for all properties in FOo f.set(foo.get()); return f; }
阅读更多http://adtmag.com/articles/2000/01/18/effective-javaeffective-cloning.aspx
请记住, clone()
不能用于开箱即用。 你将不得不实现Cloneable
并覆盖public
的clone()
方法。
有几个替代方法,这是可取的(因为clone()
方法有很多devise问题,如其他答案中所述),复制构造函数将需要手动工作:
-
BeanUtils.cloneBean(original)
创build一个浅的克隆,就像Object.clone()
创build的一样。 (这个class来自commons-beanutils ) -
SerializationUtils.clone(original)
创build一个深层克隆。 (即整个属性图被克隆,不仅是第一级)(来自commons-lang ),但所有的类都必须实现Serializable
-
Java深度克隆库提供了深度克隆,无需实现
Serializable
克隆()的devise有几个错误(见这个问题 ),所以最好避免它。
从Effective Java 2nd Edition ,项目11:明智地重写克隆
鉴于与Cloneable相关的所有问题,可以肯定的是,其他接口不应该扩展它,而为inheritancedevise的类(Item 17)不应该实现它。 由于它的许多缺点,一些专家程序员只是简单地select不覆盖克隆方法,除非可能复制数组,否则不要调用它。 如果您devise了inheritance类,请注意,如果您select不提供行为良好的受保护的克隆方法,那么子类就不可能实现Cloneable。
本书还介绍了复制构造函数对Cloneable / clone的许多优点。
- 他们不依赖风险倾向的超语言对象创build机制
- 他们不要求不可强制遵守稀less的文件规定
- 它们不会与正确使用最终字段相冲突
- 他们不会抛出不必要的检查exception
- 他们不需要演员。
所有的标准集合都有复制构造函数。 使用它们。
List<Double> original = // some list List<Double> copy = new ArrayList<Double>(original);
请记住,复制构造函数将类types限制为复制构造函数的类types。 考虑一下这个例子:
// Need to clone person, which is type Person Person clone = new Person(person);
如果person
可能是Person
的子类(或者Person
是一个接口),这不起作用。 这是克隆的关键,它可以在运行时dynamic地克隆适当的types(假设clone被正确实现)。
Person clone = (Person)person.clone();
要么
Person clone = (Person)SomeCloneUtil.clone(person); // See Bozho's answer
现在person
可以是任何types的Person
假设clone
是正确实施。
另请参阅: 如何正确覆盖克隆方法? 。 Java中的克隆工作被打破了,要做到这一点很困难 ,即使这样做实际上并不能提供太多的东西 ,所以这并不值得。
非常悲伤:Cloneable / clone和构造函数都不是很好的解决scheme:我不想知道实现类! (例如 – 我有一个地图,我想要复制,使用相同的隐藏的MumbleMap实现)我只是想复制,如果这样做是支持的。 但是,唉,Cloneable没有克隆方法,所以没有什么可以安全地进行types转换来调用clone()。
不pipe最好的“拷贝对象”库是什么,Oracle都应该把它作为下一个Java版本的标准组件(除非它已经被隐藏在某处)。
当然,如果更多的图书馆(例如 – 集合)是不可变的,这个“复制”任务就会消失。 但是接下来我们将开始deviseJava程序,比如“类不变式”,而不是“破坏性”的“bean”模式(创build一个破损的对象,直到变得足够好)。