“将类对象直接分配给同一个类的另一个对象”和“使用clone()”有什么区别

时间:2015-08-18 11:29:20

标签: java clone

我是Java编码新手。我对获取一个对象的副本有疑问。

我尝试将obj分配给另一个具有相同Class的对象,并且它有效。我通过访问两个对象中的类的项目来确认它,它们是相同的。那么clone()的用途是什么?

代码示例:

class student
{
  int id;
  String name;
}

student s1 = new student();
student s2= new student();
s1.id =10;
s2=s1;

所以s2也与s1的副本相同 - 是吗?那么克隆需要什么呢?

3 个答案:

答案 0 :(得分:3)

分配对象只是指向创建对象的引用。但克隆与整个对象完全相同。 尝试使用新引用更改值,实际对象属性将被更改,但在您克隆时,只有新创建的对象才会被更改,实际对象保持不变。

答案 1 :(得分:2)

clone()方法保存额外的处理任务,以创建对象的精确副本。如果我们使用new关键字执行它,则需要执行大量处理才能使用对象克隆。

答案 2 :(得分:1)

将一个对象分配给另一个对象时,它仅引用同一位置。即两个对象具有相同的存储位置。如果选中,则两个对象的属性值都相同。

但是,它暴露了一个问题。每当更新第一个对象时,第二个对象的值也会更新。

示例:

public class Student implements Cloneable{

int id;
String name;

public Student(int id, String name) {
    this.id = id;
    this.name = name;
}

public static void main(String[] args) throws CloneNotSupportedException {
    Student s1 = new Student(10, "A");
    Student s2 = s1;                        //simply assigning the s1 object's reference to s2
    Student s3= (Student)s1.clone();        //assigning s1 object's clone to s3

    System.out.printf("Before updation::s1.id->%d, s1.name->%s\n",s1.id, s1.name);
    System.out.printf("Before updation::s2.id->%d, s2.name->%s\n",s2.id, s2.name);
    System.out.printf("Before updation::s3.id->%d, s3.name->%s\n",s3.id, s3.name);

    s1.id = 20;
    s1.name= "Z";

    System.out.printf("After updation::s1.id-%d, s1.name->%s\n",s1.id, s1.name);
    System.out.printf("After updation::s2.id-%d, s2.name->%s\n",s2.id, s2.name);
    System.out.printf("After updation::s3.id-%d, s3.name->%s\n",s3.id, s3.name);
}
}

<强>输出:
Before updation::s1.id->10, s1.name->A
Before updation::s2.id->10, s2.name->A
Before updation::s3.id->10, s3.name->A
After updation::s1.id-20, s1.name->Z
After updation::s2.id-20, s2.name->Z
After updation::s3.id-10, s3.name->A

通常克隆对象的方法,创建同一个类的新实例,并将所有字段复制到新实例并返回它。这只不过是浅色的副本。 Object类提供克隆方法并为浅拷贝提供支持。它返回'Object'作为类型,您需要显式地转换回原始对象。

因此,当您更改原始对象的值时,克隆对象的值保持不变。

由于Object类具有clone方法(受保护),因此无法在所有类中使用它。要克隆的类应该实现克隆方法并覆盖它。它应该为复制提供它自己的含义,或者至少它应该调用super.clone()。此外,您必须实现Cloneable标记接口,否则您将获得CloneNotSupportedException。