Java克隆方法如何工作?

时间:2013-07-27 12:08:11

标签: java

public class Student implements Cloneable {
    public Student clone() {
        Student clonedStudent = (Student) super.clone();
        return clonedStudent;
    }
}

为什么Java返回student对象而不是返回对象类对象。因为我们正在使用超级。这是否意味着Java本身在克隆方法中提供浅层克隆?

5 个答案:

答案 0 :(得分:13)

java cloning是field by field copy,即因为Object类不知道将调用clone()方法的类的结构。

1)如果该类具有仅原始数据类型成员,则将创建该对象的全新副本,并且将返回对新对象副本的引用

2)如果类包含任何类类型的成员,则只复制对这些成员的对象引用,因此原始对象和克隆对象中的成员引用引用相同的对象

请参阅此链接object cloning in java

答案 1 :(得分:9)

了解docs对此的评价:

  

...因此,此方法执行此对象的“浅拷贝”,而不是a   “深层复制”操作。

另见this link

  

如果类只有原始数据类型成员那么完全   将创建对象的新副本并引用新的   将返回对象副本。但是,如果该类包含成员   任何类类型然后只有对象引用那些成员   复制并因此将原始对象中的成员引用为   以及克隆的对象引用同一个对象。

答案 2 :(得分:4)

clone()方法就像一个复制构造函数。

它创建并返回对象的副本。 由于对象类具有克隆方法(受保护),因此您无法在所有类中使用它。要克隆的类应该实现克隆方法并覆盖它。它应该为复制提供自己的意义,或者至少它应该调用super.clone()。此外,您必须实现Cloneable标记接口,否则您将获得CloneNotSupportedException。当你调用super.clone()时,你依赖于Object类的实现,你得到的是一个浅拷贝。

您可以提供Wiki Page以获得更多理解。

对于克隆对象,应该实现接口Cloneable

如果您尝试在未实现Cloneable接口的类中使用clone方法,则会抛出CloneNotSupportedException

答案 3 :(得分:0)

根据来自clone()的{​​{3}} Object生成对象所在的“浅层”副本。

如果您正在实现clone(),那么约定是您从super.clone()获得初始副本,然后实现修改此返回对象的其余克隆操作。

答案 4 :(得分:0)

java.lang.Object在Java中提供了clone()方法的默认实现。它在Object类中声明为受保护和本机,因此在本机代码中实现。由于它通过调用super.clone()方法返回对象的clone()的约定,所以任何克隆过程最终都会到达java.lang.Object clone()方法。此方法首先检查相应的对象是否实现了Cloneable接口,这是一个标记接口。如果该实例没有实现Cloneable,那么它会在Java中抛出CloneNotSupportedException,这是一个经过检查的异常,在克隆对象时总是需要处理它。 在java中,如果一个类需要支持克隆,则必须执行以下操作:

A)您必须实现Cloneable接口。 B)您必须从Object类重写clone()方法。 [有点奇怪。 clone()方法应该在Cloneable接口中。]

下面给出了关于clone()方法的Java文档(格式化和提取)。 / * 创建并返回此对象的副本。 " copy"的确切含义可能取决于对象的类。 一般意图是,对于任何对象x,表达式: 1)x.clone()!= x将为真//保证克隆对象将具有单独的内存地址分配。 2)x.clone()。getClass()== x.getClass()将为true,但这些不是绝对要求。原始对象和克隆对象应该具有相同的类类型,但它不是必需的。 3)x.clone()。equals(x)将为true,这不是绝对要求。原始和克隆对象应该使用equals()方法相等,但它不是必需的。 * /

让我们看一个例子:

public class MyClone {
    int x;
    public static void main(String[] args) throws
       CloneNotSupportedException {
        MyClone c = new MyClone();
        MyClone a = (MyClone) c.clone();  // Type-cast is required
    }
}

因为clone()是Object类的一部分,而Object不会实现Cloneable接口,所以当我们自己的类不实现Cloneable接口时,JVM将不知道这个类是否有资格进行克隆,所以CloneNotSupportedException出来了。

当我们说MyClone a =(MyClone)c.clone();时,只有两件事是可能的:

它将返回克隆的对象。

或者它会抛出CloneNotSupportedException。

很明显,当你想要克隆对象时,不必在你的类中实现clone(),如果你不这样做,Object中的clone()方法被声明为protected - 只有子类和同一个包的成员将能够在该对象上调用clone()。如果你想改变它,你应该覆盖它并公开它。

在clone()方法调用之前检查:

if(c instanceof Cloneable) {
    MyClone a = (MyClone) c.clone();
}

注意:调用clone()时不会调用构造函数。我们有责任正确设置该类的所有成员变量。

实施

Room.java
public class Room {
 private String roomSize;
 public Room(String roomSize){
  this.roomSize = roomSize;
}
 //Any Getters-Setters goes here
}
Flat.java
public class Flat implements Cloneable {
 private String flatNumber;
 private Room room;
 public Flat(String size,Room room){
   this.size = size;
   this.room = room;
 }
 public Object clone() {
  try {
   return (Flat)super.clone();
 }
  catch (CloneNotSupportedException e) {
   System.out.println("CloneNotSupportedException comes out : "
   +e.getMessage());
  }
 }
//Any Getters-Setters goes here
}
Main.java
public class Main {
  public static void main(String[] args) {
   Room room = new Room("40 X 40");
   Flat flat1 = new Flat(403 , room);
   Flat flat2 = (Flat)flat1.clone();
  }
}

这里super.clone()在clone()中被调用。我们知道,clone()在Object中声明,因此它被每个Java对象继承。调用super.clone()复制我们的超类'字段并制作字段的按位副本。这称为浅拷贝,这意味着当您使用clone()复制Flat时,字段的flatNumber将被复制其各自的值,但是空间被引用复制 - 逐位复制,内存地址被复制。

您对原始对象的空间所做的任何更改都将反映在克隆对象中,反之亦然。要解决这个问题,我们需要深层复制。现在,我们需要更改Room类,并实现" Cloneable" interface和clone()方法,然后在Flat对象的clone()方法中调用Room对象的clone()方法。

新实施

Room.java
public class Room {
    private String roomSize;
    public Room(String roomSize){
       this.roomSize = roomSize;
   }
    public Object clone() {
       try {
         return (Room)super.clone();
     }
      catch (CloneNotSupportedException e) {
       System.out.println("CloneNotSupportedException comes out : "
    +e.getMessage());
     }
   }
   //Any Getters-Setters goes here
}
Flat.java
public class Flat implements Cloneable {
    private String flatNumber;
 private Room room;
 public Flat(String size,Room room){
   this.size = size;
   this.room = room;
 }
    public Object clone() {
      Flat flat = null;
      try {
         flat = (Flat)super.clone();
     }
      catch (CloneNotSupportedException e) {
          System.out.println("CloneNotSupportedException comes out : "
    +e.getMessage());
     }
     flat.room = (Room) room.clone();
         return flat;
   }
    //Any Getters-Setters goes here
}
Main.java
public class Main {
    public static void main(String[] args) {
       Room room = new Room("40 X 40");
       Flat flat1 = new Flat(403, room);
       Flat flat2 = (Flat)flat1.clone();
   }
}

我希望这能更好地理解克隆及其实现。

感谢http://interviewguess.blogspot.in/2017/02/how-does-clone-method-work.html