如何创建用Java创建的数据类型的副本?
如果我有课:
public class MyType
{
private List<Integer> data;
private boolean someFlag;
public MyType(List<Integer> myData, boolean myFlag)
{
this.data = myData;
this.myFlag = someFlag;
}
}
现在,如果我创建MyType的一个实例,我该如何做它的深度复制?我不希望新对象指向旧引用,而是一个全新的实例
在这种情况下,我应该实现Cloneable接口,还是将a用于浅拷贝
我不能只做:
MyType instance1 = new MyType(someData, false);
MyType instance2 = new MyType(instance1.getData(), instance1.getFlag());
我担心MyType的新实例指向其“data”变量的同一引用。所以我需要完全复制它
因此,如果我有一个现有对象:
MyType someVar = new MyType(someList, false);
// Now, I want a copy of someVar, not another variable pointing to the same reference.
有人能给我指出正确的方向吗
# 1 楼答案
你应该实现
Cloneable
你定义了“你类型的副本”的确切含义。有时需要有一个类型,该类型包含一个字段,该字段的内容在多个副本中保持不变(=在所有复制实例中对同一对象的引用)您必须自己注意,所有字段实际上都会复制到一个新实例中。int、long等基本数据类型在直接存储时被复制,它们从不包含引用
如果有字段指向任何类型的对象引用,则需要找到一种机制来创建每个字段的副本
通常,在调用
.clone()
之后,您确实有一个浅拷贝。如果(且仅当)类中使用的所有类型本身都正确地实现了Cloneable,那么就会得到一个完全递归的深度副本根据JavaDoc (Object.clone())
Clonable
的意思是:请记住,这是一般的意图,而不是强制性合同
# 2 楼答案
实现iClonable
# 3 楼答案
首先:您的代码示例有一些命名问题:是myFlag还是someFlag
许多开发人员会放弃Cloneable,在需要深层拷贝时,只为类创建一个拷贝构造函数:
复制构造函数非常常见,可以在许多集合实现中找到。出于清晰的原因,我更喜欢它们而不是实现Cloneable。同样值得注意的是,即使是强大的Joshua Bloch在Effective Java(第二版第61页)中也说,复制构造函数比可克隆/克隆有许多优势
如果你没有他的书,就去拿吧
# 4 楼答案
您可以让对象图中的所有类实现
Cloneable
,并提供手动克隆。因为在您的情况下,它只有一个列表(即一个非常小的对象图),所以您最好使用复制构造函数:但请记住,在这种情况下,列表的内容仍然是相同的对象,因此它不会是真正的深度副本。在你的例子中,这些是
Integer
,所以没什么大不了的。但如果你改变它,要小心如果需要克隆更大的对象图,则分两步进行:
Serializable
接口它使用java中的序列化机制进行深度复制
或者,您可以使用this library——它不需要
Serializable
接口,并使用反射进行深度复制# 5 楼答案
您的类MyType必须实现Cloneable。然后你可以打电话给someVar。克隆()