我有一个数组,我想为其创建一个独立的副本。其中之一的变化根本不会影响另一个。
目前,我尝试的所有操作均在一个对象上创建了两个引用。默认的clone()
方法也无法正常工作。
JButton[][] old = game.getFields().clone(); // getFields() returns a two dimensional array
答案 0 :(得分:2)
用于复制数组的方法主要取决于实际情况。只要我们使用原始类型数组,就可以使用System和Arrays类提供的任何方法。
使用系统类
int[] array = {23, 43, 55};
int[] copiedArray = new int[3];
System.arraycopy(array, 0, copiedArray, 0, 3);
使用数组类
int[] array = {23, 43, 55, 12};
int newLength = array.length;
int[] copiedArray = Arrays.copyOf(array, newLength);
对于非基本类型,我们需要对数组进行深层复制。
对于深层复制,它已经回答: How do you make a deep copy of an object in Java?
答案 1 :(得分:0)
假设您有对象object
。默认的克隆方法将创建object
的新实例,即object != object.clone();
,但是其中对其他可变对象的引用也不会是新实例。 object
的新实例在可以修改其子对象而不影响原始子对象的意义上将不是独立的。但是,对于原始类型,它工作得很好,因为在构造克隆时将它们作为值而不是引用进行传递。这称为“浅副本”。
对于“深层复制”,您实际上需要为希望独立于原始对象进行操作的每个可变子对象创建新实例。您可以编写一些代码来执行此操作,或者查看深度复制API。
要编写自己的解决方案,您将在寻找一种实现与“复制构造函数”相同的方法的方法-一种将相同对象类型用作参数并使用其值(而非引用)的构造函数构造自己的实例。如果由于方法和字段的安全性原因,如果您不拥有该对象,则可能会很困难。 clone()方法不好,因为您不拥有该对象,并且其功能与编写自定义复制方法相同。
您最好的选择是对它进行序列化和反序列化,并且已经有一些强大的API用于此目的。看一下Google的GSON API。以下是通过Google找到的快速链接,值得一读:http://www.baeldung.com/java-deep-copy
.clone()上的Oracle: https://docs.oracle.com/javase/10/docs/api/java/lang/Object.html#clone()
创建并返回此对象的副本。 “复制”的确切含义可能取决于对象的类别。通常的意图是,对于任何对象x,表达式:
x.clone() != x
将为真,并且表达式:
x.clone().getClass() == x.getClass()
是正确的,但这不是绝对要求。通常情况是:
x.clone().equals(x)
将是正确的,这不是绝对要求。
按照惯例,应该通过调用super.clone获得返回的对象。如果一个类及其所有超类(对象除外)都遵守此约定,则x.clone()。getClass()== x.getClass()就是这种情况。
按照惯例,此方法返回的对象应独立于该对象(正在克隆)。为了实现这种独立性,可能有必要在返回super.clone之前修改该对象的一个或多个字段。通常,这意味着复制构成要克隆对象的内部“深度结构”的任何可变对象,并用对副本的引用替换对这些对象的引用。如果一个类仅包含原始字段或对不可变对象的引用,那么通常情况下,无需修改super.clone返回的对象中的任何字段。
类Object的方法clone执行特定的克隆操作。首先,如果该对象的类未实现Cloneable接口,则抛出CloneNotSupportedException。注意,所有数组都被认为实现了Cloneable接口,并且数组类型T []的clone方法的返回类型为T [],其中T是任何引用或原始类型。否则,此方法将创建此对象类的新实例,并使用该对象相应字段的内容完全初始化其所有字段,就像通过赋值一样;字段的内容本身不会被克隆。因此,此方法执行此对象的“浅复制”,而不是“深复制”操作。