Java中克隆对象的必要性是什么?

7

我正在阅读关于Java中克隆的内容,如何创建对象的浅/深拷贝等。

我想知道为什么需要在Java中创建对象副本?任何实时示例都有助于理解。


可能是Java中的clone()方法的重复问题... 或者是https://dev59.com/O2025IYBdhLWcg3wKCf-或https://dev59.com/bG435IYBdhLWcg3wrSFB等等。在提出新问题之前,请使用搜索功能;许多问题已经被问过并得到了回答。 - Brian Roach
嗨,Brian。我确实搜索过了,但在大多数帖子中只给出了实现或浅拷贝和深拷贝之间的区别。我知道浅/深克隆。我只想知道在Java中克隆对象的原因是什么? - Anand
6个回答

8
拥有一个克隆的副本意味着你可以拥有“之前”和“之后”的版本。在测试过程中,你可以保留原始版本并使用副本。通过简单地恢复到原始版本,你可以提供撤消操作。

我理解了。但如果您能够告诉我一些现实生活中的例子,在这些例子中我必须放弃原始对象并测试对象的副本,这将使事情更加清晰明了。 - Anand
我认为@biziclop提出了一种情景,即您想要测试复制。也就是说,您想要测试复制是否成功,可能是在交易中。如果由于验证问题或数据库事务失败而无法成功复制,您只需将其丢弃并恢复到原始状态,而无需重新创建它。 - DOK
是的,我明白了。还有一件事,我读到过当初始化一个对象太昂贵时,我们会克隆一个对象。因此,我们可以克隆现有的对象,只更改对我们新实例重要的属性,而不是创建一个新对象。你能详细解释一下吗? - Anand
@Anand,你得到了答案吗?与克隆相比,初始化对象的操作是否更昂贵? - Narendra Pandey

4

很多时候,您希望使用不可变对象,这种情况下,克隆是您代码的重要部分。例如,如果您有一个具有列表或数组类型字段的不可变对象,则getter应始终返回列表或数组的克隆以保留不可变性。

另一个典型用例是当您想要进行“事务性”修改时,即调用几个状态更改方法,但只有在所有方法都成功时才希望看到结果。


正如你所说,如果将列表作为不可变对象的字段,我必须在getter中返回该列表的克隆副本,但我可以使用“new”创建一个新列表,然后返回它。此外,List接口没有克隆方法,只有实现类才有克隆方法。那么为什么要使用克隆呢? - Anand
@anand 我的意思是克隆作为一种操作。其中一种克隆的方法确实是使用复制构造函数。另一种方法是实现一个 clone() 方法。无论你如何实现克隆,一种方法和另一种方法都一样好。 - biziclop

2

1
作为克隆本身表示的复制某物的副本,因此在Java中,当我们说对象克隆时,它意味着创建或拥有现有对象的另一个相同对象。
什么时候进行克隆?当我们发现每次创建新对象都很耗时,或者我们需要具有与已创建对象相同或略有不同的新对象时,我们就会使用克隆。
Java中的克隆分为3种类型:
- 浅拷贝 - 深拷贝 - 克隆
浅拷贝是将对象的状态复制到另一个对象中的过程,但两个对象都指向堆区中的同一引用。
深拷贝则创建了两个独立的对象,在深拷贝中,将一个对象的每个字段都复制到另一个对象中。
现在,为了克服这个困难,Java中的第三个类别是克隆概念。
在Java中,克隆是通过实现Cloneable接口来完成的。 Cloneable是标记接口。

想要了解更深入的克隆知识,请参考:Java中的克隆


0

您可以使用对象的深克隆副本,因为在某些方法中您可能需要部分结果,并且希望稍后使用。


0
作为帮助保护封装性(从而使您的代码更加健壮)的一种方式,您可以在从getter返回对象之前对其进行克隆。例如,getDate方法可能会在返回调用者之前克隆日期字段。

正如你所说,我可以在返回之前克隆一个日期字段,但我也可以创建一个新的日期对象。为什么我要在这里使用克隆? - Anand

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接