我目前正在为 Java 开发图形库。如您所料,存在一个 Vertex
类(class)。该类包含类型为 VertexData<T>
的对象而它本身可以包含任何东西。
(我知道这可能是多余的,我可以做 Vertex<T>
但为了这个问题的目的,这并不重要)。
我做了VertexData<T>
实现 Cloneable
并且有一个public VertexData<T> clone()
通过序列化和反序列化调用返回深拷贝的方法 Object
,非常像描述的here
现在的问题是,既然我有一个深拷贝方法,那么也有一个浅拷贝有意义吗?如果是这样,浅拷贝优于深拷贝的情况是什么?
更新:由于大多数答案和评论都以某种方式解释了什么是浅拷贝,我觉得我必须澄清一下。我确实知道浅拷贝是什么,它是如何工作的,一切。我的问题是,既然我正在开发的是一个库,而且我确实创建了一个深拷贝方法,那么是否也可以提供一个浅拷贝方法?
我还要在这里补充一点,VertexData<T>
中不包含原始类型。类。
因此,在用于存储图库 的顶点数据的容器类的上下文中,是否需要浅拷贝?
如果是这样,你能在我正在开发的内容中想出一个例子吗?
如果不是,我应该只为了完整性而添加浅拷贝方法吗?
这是一个好的做法还是无关紧要?
最佳答案
类似List<Point>
的容器类型可能在某些情况下用于保存一组 X,Y 坐标对,但在其他情况下可能用于识别一组可移动的点,这些点被其他人使用代码。前一种情况可以分割为子情况,其中 List<Point>
的所有者也是Point
的独家拥有者其中的实例并可以随意修改它们,或者所有者永远不会修改这些实例但可以与 promise 不修改它们的代码共享对它们的引用。
如果List<Point>
用于封装(X,Y)坐标对,但所有者可能会修改Point
其中包含的对象,然后是 List<Point>
的适当克隆必须持有对 Point
副本的引用有问题的对象。如果它封装了坐标对,但没有人会修改其中的对象(并且克隆列表的接收者不会将对其中对象的引用公开给可能修改它们的任何代码),然后适当克隆 List<Point>
可以保留对原始 Point
的引用元素或其副本;前者会更快,但后者在语义上仍然是正确的。
如果List<Point>
用于识别 Point
可能被其他代码修改的实例,任何此类修改都需要反射(reflect)在 List<Point>
中本身,那么一个合适的克隆必须持有对相同Point
的引用对象作为原始列表。如果一个克隆人持有那些 Point
的副本对象,那么它将不再包含与原始列表相同的语义信息。
如果Java
根据它们是使用独占的可变实例还是可共享的不可变实例来封装值,或者它们是否用于识别其中的东西来分离集合类型,那么就有可能有一个单一的“克隆”概念,而不是要求“深”和“浅”克隆。但是,如果集合类型之间没有这种区别,则有必要使用克隆方法来根据集合中的内容执行任何需要的操作。
关于java - 真的需要浅拷贝吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30984836/