为什么Object类的clone()方法会提供对象的深层副本?
根据JAVA文档,super.clone()被调用时会返回该对象的浅表副本。 在下面的代码中,我有两个对象名称和ID ; 和一个基本变量num 。 当在第一个对象上调用super.clone()方法时,除了仅有num的预期副本外,它似乎还创建了对象的深层副本(名称和ID)。 克隆对象obj后,我更改了它的名称和id字段。 如果正在创建浅拷贝,这些更改应该反映在克隆的对象中。 我对吗?
public class Cloning implements Cloneable {
String name;
int num;
Integer id;
Cloning(String name,int num,Integer id)
{
this.name = name;
this.num = num;
this.id = id;
}
public Object clone()
{
try
{
return super.clone();
}
catch(CloneNotSupportedException E)
{
System.out.println(E.getMessage());
return null;
}
}
public void print()
{
System.out.println(name);
System.out.println(num);
System.out.println(id);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Cloning obj = new Cloning("Annu",203,new Integer(3));
Cloning obj1 = (Cloning)obj.clone();
obj.name = "Annu_modified";
obj.num = 204;
obj.id = new Integer(4);
obj.print();
obj1.print();
}
}
我在运行代码时得到以下输出:
Annu_modified
204
4
Annu
203
3
让我们看看你的例子中的一节: obj.id = new Integer(4);
。 在这里你不会改变id的内部表示 - 你正在给id引用分配新的实例。 Integer
和String
都是不可变的,因此很难感受到浅拷贝与深拷贝的区别。 尝试添加例如ArrayList
属性,并且为了修改它,您可以添加一个新元素obj.myList.add(13);
name和id字段是对String和Integer类型的对象的引用。 当您制作浅拷贝时,新拷贝将指向名称和ID相同的对象。
然后当你这样做
obj.name =“Annu_modified”;
您将obj.name更改为引用String类型的新对象,而obj1.name继续引用旧对象。 如果你可以改变对象的obj.name,它会改变两者。 然而,对于一个字符串,你不能使它成为一个所谓的不可变对象。
试试这个测试
Cloning obj = new Cloning("Annu",203, 1000);
Cloning obj1 = (Cloning)obj.clone();
System.out.println(obj.id == obj1.id);
它打印true
,它意味着克隆对象的id指向Integer的同一个实例,如果它是深度克隆,它将打印false
上一篇: Why is the Object class's clone() method giving a deep copy of object?