Java 数组的克隆方法

Posted

技术标签:

【中文标题】Java 数组的克隆方法【英文标题】:Clone method for Java arrays 【发布时间】:2012-12-18 10:54:06 【问题描述】:

Java 中的 clone() 方法在数组上使用时究竟返回什么? 它是否返回一个包含从原始数据复制的数据的新数组?

例如:

int[] a = 1,2,3;
int[] b = a.clone();

【问题讨论】:

您检查过文档并自己尝试了吗?有什么困惑? 通过以下链接了解 clone()。 clone (Java method) 和 What is cloning。这些链接将点亮您提出的问题。 这似乎与建议的问题不重复,该问题专门询问有关克隆数组引用的对象的问题。这个问题没有问这个问题,它的例子是一个基元数组。 @AndyThomas 如果您的重新打开是合理的,请删除指向副本的链接,否则请重新关闭问题。 【参考方案1】:

当对数组调用 clone 方法时,它会返回对包含(或引用)与源数组相同元素的新数组的引用。

所以在您的示例中,int[] a 是在堆上创建的单独对象实例,int[] b 是在堆上创建的单独对象实例。 (记住所有数组都是对象)。

    int[] a = 1,2,3;
    int[] b = a.clone();

    System.out.println(a == b ? "Same Instance":"Different Instance");
    //Outputs different instance

如果要修改 int[] b,则更改不会反映在 int[] a 上,因为这两个是单独的对象实例。

    b[0] = 5;
    System.out.println(a[0]);
    System.out.println(b[0]);
    //Outputs: 1
    //         5

当源数组包含对象时,这会变得稍微复杂一些。 clone 方法将返回对新数组的引用,该数组引用与源数组相同的对象。

所以如果我们有 Dog 类...

    class Dog

        private String name;

        public Dog(String name) 
            super();
            this.name = name;
        

        public String getName() 
            return name;
        

        public void setName(String name) 
            this.name = name;
        

    

然后我创建并填充了 Dog 类型的数组...

    Dog[] myDogs = new Dog[4];

    myDogs[0] = new Dog("Wolf");
    myDogs[1] = new Dog("Pepper");
    myDogs[2] = new Dog("Bullet");
    myDogs[3] = new Dog("Sadie");

然后克隆狗……

    Dog[] myDogsClone = myDogs.clone();

数组引用相同的元素...

    System.out.println(myDogs[0] == myDogsClone[0] ? "Same":"Different");
    System.out.println(myDogs[1] == myDogsClone[1] ? "Same":"Different");
    System.out.println(myDogs[2] == myDogsClone[2] ? "Same":"Different");
    System.out.println(myDogs[3] == myDogsClone[3] ? "Same":"Different");
    //Outputs Same (4 Times)

这意味着如果我们修改通过克隆数组访问的对象,则更改将在我们访问源数组中的相同对象时反映出来,因为它们指向相同的引用。

    myDogsClone[0].setName("Ruff"); 
    System.out.println(myDogs[0].getName());
    //Outputs Ruff

但是,对数组本身的更改只会影响该数组。

    myDogsClone[1] = new Dog("Spot");
    System.out.println(myDogsClone[1].getName());
    System.out.println(myDogs[1].getName());
    //Outputs Spot
    //        Pepper

如果您大致了解对象引用的工作原理,就很容易理解对象数组如何受到克隆和修改的影响。为了进一步了解引用和原语,我建议阅读这篇出色的 article。

Gist of Source Code

【讨论】:

我听说使用.remove() 不会影响原始数组。只有Mutating 方法会影响原始数组。对吗??【参考方案2】:

clone() 方法创建并返回此对象的副本。 “复制”的确切含义可能取决于对象的类别。一般意图是,对于任何对象 x,表达式:

 x.clone() != x

会是真的,那表达式:

 x.clone().getClass() == x.getClass()

确实如此,但这些不是绝对要求。

虽然通常是这样的:

 x.clone().equals(x)

会是真的,这不是绝对的要求。

按照约定,返回的对象应该通过调用super.clone来获取。如果一个类和它的所有超类(Object 除外)都遵守这个约定,那么x.clone().getClass() == x.getClass() 就是这种情况。

【讨论】:

这只是j.l.Objectclone() 方法的javadoc 的摘录,我看不出它是如何回答这个问题的。

以上是关于Java 数组的克隆方法的主要内容,如果未能解决你的问题,请参考以下文章

有没有在 jQuery 中克隆数组的方法?

js 数组克隆方法 小结

深度克隆实用程序推荐 [关闭]

深度克隆实用程序推荐 [关闭]

clone()方法

关于数组的深度克隆(未完待续)