真的需要浅拷贝吗?

时间:2015-06-22 16:12:06

标签: java generics deep-copy

我目前正在研究Java的图形库。正如您所期望的那样,存在Vertex类。该类包含VertexData<T>类型的对象,它本身可以包含任何内容。
(我知道这可能是多余的,我可以做Vertex<T>,但出于问题的目的,这无关紧要)。
我通过序列化和反序列化调用VertexData<T>Cloneable实现public VertexData<T> clone()并使用Object方法返回深层副本,非常类似于{{3} }

现在的问题是,既然我有深度复制方法,那么还有一个浅拷贝是否有意义?如果是这样的话,那么浅拷贝比深拷贝更适合这种情况呢?

更新:由于大多数答案和评论都包含对浅层副本的某种解释,我觉得我必须澄清一下。我知道浅色副本是什么,它是如何工作的,一切。我的问题是,因为我正在开发一个,并且因为我确实创建了一个深层复制方法,所以为浅层复制方法提供方法是否有意义?

我也会在这里添加VertexData<T>类中没有原始类型 因此,在用于存储图形的顶点数据的容器类的上下文中,是否需要浅层复制?
如果是这样,你能想到一个例子,在我正在发展的范围内吗?
如果不是我应该只为了完整性添加浅拷贝方法?
这是一种好的做法还是无所谓?

4 个答案:

答案 0 :(得分:3)

真正归结为要求。知道你的对象不仅仅有原始字段,它应该(并且谢天谢地)有一个deep copy。无论是使用shallow还是deep,都没有“硬性规定”。由于它是“基于要求”,因此在对另一个答案的评论中提供@RyanJ指出是安全的。

如果您希望浅浅地复制您的集合或对象,并对一个属性进行更改,它将同时更改引用和复制的对象。另一方面,如果您希望深度复制并能够更改对象或对象副本的值,并且不会影响副本和原始副本,则只需要深层复制。这一切都归结为要求以及您需要对象/系统做什么。我的最终建议是两者兼顾。

答案 1 :(得分:1)

List<Point>这样的容器类型在某些情况下可能用于保持一堆X,Y坐标对,但在其他情况下可用于识别一堆可移动的点,由其他代码使用。前一种情况可以细分为子句,其中List<Point>的所有者也是其中Point个实例的独占所有者,并且可以随意修改它们,或者所有者永远不会修改这些实例但可以使用承诺不修改它们的代码来共享对它们的引用。

如果List<Point>用于封装(X,Y)坐标对,但所有者可能会修改其中保存的Point个对象,那么List<Point>必须正确克隆保留对相关Point个对象副本的引用。如果它封装了坐标对,但没有人会修改其中的对象(并且克隆列表的接收者不会将对其中对象的引用暴露给任何可能修改它们的代码),那么List<Point>的正确克隆就可以了保留对原始Point对象或其副本的引用;前者会更快,但后者在语义上仍然是正确的。

如果List<Point>用于识别可能被其他代码修改的 Point个实例,并且任何此类修改都需要反映在List<Point>本身中,然后一个适当的克隆必须保持对与原始列表相同的Point个对象的引用。如果克隆要保留那些Point个对象的副本,那么它将不再保留与原始列表相同的语义信息。

如果Java根据是否使用专有的可变实例或可共享的不可变实例来封装值,或者它们是否用于识别其中的内容,那么它们是否具有隔离的集合类型,则可能只有一个概念: “克隆”,而不是要求“深入”和“浅层”克隆。但是,如果没有集合类型之间的区别,就必须有克隆方法,可以根据集合中的内容做任何需要的事情。

答案 2 :(得分:0)

您不需要浅色副本。浅拷贝只会将新的引用变量分配给内存中已存在的对象。一个&#39; =&#39;操作员将完成工作。有关详细信息,请仔细阅读此帖 - In Java, what is a shallow copy?

答案 3 :(得分:0)

是的,在少数情况下是必需的。您可以根据以下几点推断出要求。

如果对象只有原始字段,那么你应该去浅层复制。

如果对象具有对其他对象的引用,则根据要求,您应该考虑浅拷贝或深拷贝。

如果未修改引用,则不需要进行深层复制。你应该去浅层复制。

如果引用被修改,则首选深度复制。

浅拷贝:

enter image description here

如果值的元素从其他引用更改,那么浅拷贝可能会导致不必要的影响。

深拷贝:

enter image description here

在深度复制期间对数组值的任何更改引用都不会导致对引用的数组数据的更改。

你可以参考this link  通过示例了解更多相关信息。