浅拷贝是否真的需要?
我目前正在研究Java的图形库。 正如你所期望的那样,存在一个Vertex
类。 该类包含VertexData<T>
类型的对象,并且它本身可以包含任何内容。
(我知道这可能是多余的,我可以做Vertex<T>
但为了这个问题的目的不重要)。
我使VertexData<T>
实现了Cloneable
并且有一个public VertexData<T> clone()
方法,通过对调用Object
进行序列化和反序列化来返回深层副本,非常像这里描述的
现在的问题是,因为我确实有一个深层复制方法,所以也有一个浅拷贝是有意义的吗? 如果是这样的话,浅拷贝比深拷贝更受欢迎的情况是什么?
更新:由于大多数答案和评论都包含了某种浅层副本的某种解释,所以我觉得我必须澄清一点。 我知道浅拷贝是什么,它是如何工作的,一切都是如此。 我的问题是,因为它是一个我正在开发的库 ,并且由于我确实创建了一个深度复制方法,因此也可以提供浅拷贝方法吗?
我也会在这里添加, VertexData<T>
类中不包含任何基本类型。
因此,在用于存储图库的顶点数据的容器类的上下文中,是否需要浅拷贝?
如果是的话,你能想到一个例子,在我正在发展的范围内?
如果不是,我应该只为了完整性而添加浅拷贝方法吗?
这是一种好的做法还是没有关系?
像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
根据它们是使用专有的可变实例还是可共享的不可变实例来封装值,或者它们是否用于识别其中的事物,而分离了集合类型,则可能有一个“克隆”的概念,而不需要“深”和“浅”克隆。 然而,如果没有收集类型之间的这种区分,就必须有克隆方法,根据收集中的事情可以做任何需要的克隆方法。
它真的归结为要求。 知道你的对象不仅仅是原始字段,它应该(并且幸运地)具有deep copy
。 对于是shallow
还是deep
没有“硬性规定”。 既然它是“基于需求”,那么在另一个答案的评论中提供两个@RyanJ点是安全的。
如果您希望浅拷贝您的集合或对象,并对一个属性进行更改,它将同时更改引用以及复制的对象。 另一方面,如果您想深度复制并能够更改对象的值或对象的副本,而不会影响副本和原始副本,则可以使用深度副本。 这一切都归结为需求和你需要你的对象/系统做什么。 我最后的建议是做这两个。
你不需要浅拷贝。 一个浅拷贝只会为你已经存在的内存对象分配一个新的引用变量。 一个'='操作符将完成这项工作。 有关更多详细信息,请阅读此文章 - 在Java中,什么是浅拷贝?
链接地址: http://www.djcxy.com/p/86013.html上一篇: Is shallow copy really needed?
下一篇: Prevent TextIOWrapper from closing on GC in a Py2/Py3 compatible way