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

Why does Java return student object instead of returning object class object. As we are using super. Does it mean Java itself provides shallow cloning in the clone method?

4

4 回答 4

14

java cloning is field by field copy i.e. as the Object class does not have idea about the structure of class on which clone() method will be invoked.

1) If the class has only primitive data type members then a completely new copy of the object will be created and the reference to the new object copy will be returned.

2) If the class contains members of any class type then only the object references to those members are copied and hence the member references in both the original object as well as the cloned object refer to the same object.

Refer this link object cloning in java

于 2013-07-27T12:14:14.720 回答
9

看看文档是怎么说的:

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

另请参阅此链接

如果该类只有原始数据类型成员,则将创建对象的全新副本,并返回对新对象副本的引用。但是,如果类包含任何类类型的成员,则仅复制对这些成员的对象引用,因此原始对象和克隆对象中的成员引用都引用同一对象。

于 2013-07-27T12:14:43.593 回答
3

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

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

您可以参考维基页面以获得更多理解。

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

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

于 2013-07-27T12:26:55.573 回答
0

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

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

clone()下面给出了有关方法的 Java 文档(格式化和提取)。/* 创建并返回此对象的副本。“复制”的确切含义可能取决于对象的类别。一般的意图是,对于任何 object x,表达式:1)x.clone() != x将是 true //保证克隆的 object 将具有单独的内存地址分配。2)x.clone().getClass() == x.getClass()会是这样,但这些不是绝对要求。//原始对象和克隆对象应该具有相同的类类型,但这不是强制性的。3)x.clone().equals(x)将是真的,这不是绝对要求。//原始对象和克隆对象使用方法应该相等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()当您想要克隆对象时,在您的类中实现不是强制性的,如果您不这样做,则类中的clone()方法Object被声明为受保护 - 只有同一包的子类和成员才能调用clone()on物体。如果你想改变它,你应该覆盖它并将其公开。

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 go 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 go 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()被调用 inside clone()。我们知道,clone()在 中声明Object,所以它被每个 Java 对象继承。调用super.clone()复制我们超类的字段并按位复制这些字段。这称为浅拷贝,这意味着当您Flat使用 using 进行复制时,将使用它们各自的值复制clone()该字段flatNumber,但通过引用复制空间 - 逐位复制内存地址。

您对原始对象的房间所做的任何更改都将反映在克隆对象中,反之亦然。为了解决这个问题,我们需要深拷贝。现在,我们需要更改Room类以及实现Cloneable接口和clone()方法,然后clone()Room对象的方法中调用对象的clone()方法Flat

新实施

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 go 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 go 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

于 2017-02-10T13:53:13.110 回答