java.lang.Object
clone()
提供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