创建数组的独立副本[重复]

Posted

技术标签:

【中文标题】创建数组的独立副本[重复]【英文标题】:Create an independent copy of an array [duplicate] 【发布时间】:2018-11-30 05:11:56 【问题描述】:

我有一个数组,我想创建它的独立副本。其中一个的变化根本不应该影响另一个。

目前我尝试的一切都只是在一个对象上创建了两个引用。默认的clone() 方法也不起作用。

JButton[][] old = game.getFields().clone(); // getFields() returns a two dimensional array

【问题讨论】:

【参考方案1】:

用于复制数组的方法主要取决于确切的场景。只要我们使用原始类型数组,我们就可以使用 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?

【讨论】:

【参考方案2】:

假设您有对象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来获取。如果一个类及其所有超类(Object 除外)都遵守此约定,则 x.clone().getClass() == x.getClass()。

按照惯例,这个方法返回的对象应该独立于这个对象(它正在被克隆)。为了实现这种独立性,可能需要在返回 super.clone 之前修改对象的一个​​或多个字段。通常,这意味着复制任何包含被克隆对象的内部“深层结构”的可变对象,并将对这些对象的引用替换为对副本的引用。如果一个类只包含原始字段或对不可变对象的引用,那么通常情况下 super.clone 返回的对象中不需要修改任何字段。

类 Object 的方法 clone 执行特定的克隆操作。首先,如果该对象的类没有实现接口 Cloneable,则抛出 CloneNotSupportedException。请注意,所有数组都被认为实现了接口 Cloneable,并且数组类型 T[] 的克隆方法的返回类型是 T[],其中 T 是任何引用或原始类型。否则,此方法会创建此对象的类的新实例,并使用此对象的相应字段的内容来初始化其所有字段,就像通过赋值一样;字段的内容本身不会被克隆。因此,此方法执行此对象的“浅拷贝”,而不是“深拷贝”操作。

【讨论】:

以上是关于创建数组的独立副本[重复]的主要内容,如果未能解决你的问题,请参考以下文章

从数组中删除所有某些重复项[重复]

如何使用 GIT cmd 将远程分支代码的副本复制到本地分支 [重复]

在表中插入行的副本并检查重复项

Python:附加原始对象与附加对象副本[重复]

从列表的副本中删除时删除的列表元素[重复]

JavaScript:删除共享相同属性值的对象的重复项