Java Object clone方法是Java中的一种拷贝技术,它可以将一个对象的属性和状态复制到另一个新的对象中。它是一种浅拷贝,因为它只复制对象的基本数据类型(如int、float、boolean等),而不会复制引用数据类型(如String、Object、Array等)。
要使用clone方法,必须要实现Cloneable接口。Cloneable接口是一个标记性接口,它不包含任何方法。当一个类实现了Cloneable接口时,就表明该类允许其对象进行clone()方法的复制。
public class Student implements Cloneable { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override //重写Object的clone()方法 public Object clone() throws CloneNotSupportedException { //此处必须要声明CloneNotSupportedException异常 return super.clone(); //直接调用Object对象的clone()方法 } }
Java不提供克隆(复制)对象的自动机制。
克隆对象意味着逐位复制对象的内容。
要支持克隆操作,请在类中实现clone()方法。
Object类中的clone()方法的声明如下:
protected Object clone() throws CloneNotSupportedException
clone()方法声明为protected。因此,我们不能从客户端代码调用它。以下代码无效:
Object obj = new Object(); Object clone = obj.clone(); // Error. Cannot access protected clone() method
我们需要在类中声明clone()方法public克隆类的对象。
它的返回类型是Object。这意味着您将需要转换clone()方法的返回值。
假设MyClass是可克隆的。克隆代码将如下所示:
MyClass mc = new MyClass(); MyClass clone = (MyClass)mc.clone(); // Need to use a cast
Object类中的clone()方法会抛出CloneNotSupportedException。
要调用clone()方法,我们需要将调用放在try-catch块中,或者重新抛出异常。
以下代码显示了如何实现克隆方法。
class MyClass implements Cloneable { private double value; public MyClass(double value) { this.value = value; } public void setValue(double value) { this.value = value; } public double getValue() { return this.value; } public Object clone() { MyClass copy = null; try { copy = (MyClass) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return copy; } } public class Main { public static void main(String[] args) { MyClass dh = new MyClass(100.00); MyClass dhClone = (MyClass) dh.clone(); System.out.println("Original:" + dh.getValue()); System.out.println("Clone :" + dhClone.getValue()); dh.setValue(200.00); dhClone.setValue(400.00); System.out.println("Original:" + dh.getValue()); System.out.println("Clone :" + dhClone.getValue()); } }
上面的代码生成以下结果。
Original:100.0
Clone :100.0
Original:200.0
Clone :400.0
以下代码不从clone方法返回对象类型,该方法仅在Java 5或更高版本中编译。
class MyClass implements Cloneable { public MyClass clone() { Object copy = null; return (MyClass)copy; } }
下面的代码展示了如何做浅层克隆。
class MyClass implements Cloneable { private double value; public MyClass(double value) { this.value = value; } public void setValue(double value) { this.value = value; } public double getValue() { return this.value; } public Object clone() { MyClass copy = null; try { copy = (MyClass) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return copy; } } class ShallowClone implements Cloneable { private MyClass holder = new MyClass(0.0); public ShallowClone(double value) { this.holder.setValue(value); } public void setValue(double value) { this.holder.setValue(value); } public double getValue() { return this.holder.getValue(); } public Object clone() { ShallowClone copy = null; try { copy = (ShallowClone) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return copy; } } public class Main { public static void main(String[] args) { ShallowClone sc = new ShallowClone(100.00); ShallowClone scClone = (ShallowClone) sc.clone(); System.out.println("Original:" + sc.getValue()); System.out.println("Clone :" + scClone.getValue()); sc.setValue(200.00); System.out.println("Original:" + sc.getValue()); System.out.println("Clone :" + scClone.getValue()); } }
上面的代码生成以下结果。
ShallowClone类的clone()方法中的代码与MyClass类的clone()方法相同。
当ShallowClone类使用super.clone()调用Object类的clone()方法时,它会接收自身的浅拷贝。也就是说,它与其克隆共享其实例变量中使用的DoubleHolder对象。
在深层克隆中,您需要克隆对象的所有引用实例变量引用的所有对象。
class MyClass implements Cloneable { private double value; public MyClass(double value) { this.value = value; } public void setValue(double value) { this.value = value; } public double getValue() { return this.value; } public Object clone() { MyClass copy = null; try { copy = (MyClass) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return copy; } } class DeepClone implements Cloneable { private MyClass holder = new MyClass(0.0); public DeepClone(double value) { this.holder.setValue(value); } public void setValue(double value) { this.holder.setValue(value); } public double getValue() { return this.holder.getValue(); } public Object clone() { DeepClone copy = null; try { copy = (DeepClone) super.clone(); copy.holder = (MyClass) this.holder.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return copy; } } public class Main { public static void main(String[] args) { DeepClone sc = new DeepClone(100.00); DeepClone scClone = (DeepClone) sc.clone(); System.out.println("Original:" + sc.getValue()); System.out.println("Clone :" + scClone.getValue()); sc.setValue(200.00); System.out.println("Original:" + sc.getValue()); System.out.println("Clone :" + scClone.getValue()); } }
上面的代码生成以下结果。
Java 实例以下实例演示了如何遍历从Collection接口延伸出的List、Set和以键值对形式作存储的Map类型的集合,以下我们分别使用了...
随机数是任何一种编程语言最基本的特征之一,在技术开发中应用很广泛,因为有时我们需要随机生成一个固定长度的数字、字符串亦或...
JavaFX教程 -JavaFX区域图区域图是另一种类型的双轴图表。import javafx.application.Application;import javafx.scene.Group;im...
Python3 os.lchflags() 方法 Python3 OS 文件/目录方法概述os.lchflags() 方法用于设置路径的标记为数字标记,类似 chflags(),...
Python3 os.listdir() 方法 Python3 OS 文件/目录方法概述os.listdir() 方法用于返回指定的文件夹包含的文件或文件夹的名字的列...