在数组上调用clone()方法是否也会克隆其内容?

93
如果我在类型为A的对象数组上调用clone()方法,它会如何克隆其元素?复制品是否将引用相同的对象?还是对每个元素都调用(类型为A的元素).clone() ?

3
你需要对每个元素调用 clone 方法。 - Peter Lawrey
4个回答

77

clone()方法创建的是浅拷贝,这意味着元素不会被克隆。(如果它们没有实现Cloneable接口怎么办?)

如果要复制数组,您可以使用Arrays.copyOf(..)而非clone()方法(虽然对于数组来说,克隆也没问题,但对于其他类型则不行)

如果需要深度克隆,请参考此答案


下面是一个简单的示例,用于说明即使元素是Cloneable类型,clone()仍然是浅拷贝:

ArrayList[] array = new ArrayList[] {new ArrayList(), new ArrayList()};
ArrayList[] clone = array.clone();
for (int i = 0; i < clone.length; i ++) {
    System.out.println(System.identityHashCode(array[i]));
    System.out.println(System.identityHashCode(clone[i]));
    System.out.println(System.identityHashCode(array[i].clone()));
    System.out.println("-----");
}

输出:

4384790  
4384790
9634993  
-----  
1641745  
1641745  
11077203  
-----  

2
而且,如果你要这样做的话,我个人会使用System.arrayCopy - corsiKa
1
clone()是一个很好的选项,几乎只用于数组。Bloch提到他只会将其用于数组,而不会用于其他任何情况。System.arrayCopy也可以。Arrays.copyOf(..)是另一种更易于使用的替代方案。 - Bozho
我收回了之前的说法 - 我会使用 Arrays.copyOf :-) 它有一个方法签名,可以简化变量(是的,它会限制你,但对于大多数情况来说是完美的),并且至少在我的JDK中,它是使用 System.arrayCopy 实现的。感谢您的提示! - corsiKa
@Bozho,从您的例子中可以看出,array[i]和clone[i]将引用同一个对象,因此前两个sysout是相同的。但是,array[i].clone也将引用array[i]本身,那么为什么array[i].clone()会返回不同的哈希码值呢? - abhihello123
@weakstudent,“array[i].clone()”并不是指向“array[i]”。这就是示例中展示的内容。 - Dathan

19
如果我在类型为A的对象数组上调用clone()方法,它会如何克隆其元素?
数组的元素将不会被克隆。
复制品是否将引用相同的对象?
是的。
还是它会对每个元素调用(element of type A).clone()?
不,它不会对任何元素调用clone()方法。

7

当克隆一个原始类型的1D数组时,它会复制元素。这让我们想去克隆一个2D数组(数组的数组)。

请记住,由于clone()的浅拷贝实现,2D数组的克隆不起作用。

public static void main(String[] args) {
    int row1[] = {0,1,2,3};
    int row2[] =  row1.clone();
    row2[0] = 10;
    System.out.println(row1[0] == row2[0]); // prints false

    int table1[][]={{0,1,2,3},{11,12,13,14}};
    int table2[][] = table1.clone();
    table2[0][0] = 100;
    System.out.println(table1[0][0] == table2[0][0]); //prints true
}

1
你是在告诉我,我可以clone一个基本类型的一维数组并获得深拷贝吗?太棒了!那就再见了,Arrays.copyOfRange()System.arraycopy() - Janez Kuhar
2
是的!当数组被克隆时,原始类型的1D数组会被复制。 - Thamme Gowda
2
请注意,Thamme Gowda N说的是“原始数据类型”。对象数组的克隆只会是引用的克隆。 - Kristiaan
因为原始类型没有状态,它们本质上是不可变的。你不能制作原始类型的浅拷贝,因为没有引用。 - xeruf

5
克隆是数组的浅拷贝。
这个测试代码输出:
[1, 2] / [1, 2] [100, 200] / [100, 2]
因为 MutableInteger 在两个数组中作为 objects[0]objects2[0] 共享,但你可以独立地改变 objects[1] 的引用和 objects2[1]
import java.util.Arrays;                                                                                                                                 

public class CloneTest {                                                                                                                                 
    static class MutableInteger {                                                                                                                        
        int value;                                                                                                                                       
        MutableInteger(int value) {                                                                                                                      
            this.value = value;                                                                                                                          
        }                                                                                                                                                
        @Override                                                                                                                                        
        public String toString() {                                                                                                                       
            return Integer.toString(value);                                                                                                              
        }                                                                                                                                                
    }                                                                                                                                                    
    public static void main(String[] args) {                                                                                                             
        MutableInteger[] objects = new MutableInteger[] {
                new MutableInteger(1), new MutableInteger(2) };                                                
        MutableInteger[] objects2 = objects.clone();                                                                                                     
        System.out.println(Arrays.toString(objects) + " / " + 
                            Arrays.toString(objects2));                                                                
        objects[0].value = 100;                                                                                                                          
        objects[1] = new MutableInteger(200);                                                                                                            
        System.out.println(Arrays.toString(objects) + " / " + 
                            Arrays.toString(objects2));                                                               
    }                                                                                                                                                    
}                                                                                                                                                        

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接