Java 中 clone() 的使用方法
什么是 clone() 方法
clone()
方法是一个 Object 类下的方法,用于返回对象的一个副本。如果一个类要使用 clone() 方法,则这个类必须实现 Cloneable 接口并覆盖 clone()
方法,否则会抛出 CloneNotSupportedException
异常。
如何使用 clone() 方法
实现 Cloneable 接口
实现 Cloneable 接口的类是为了表明这个类是可以进行拷贝的。Cloneable 接口没有方法需要实现,只是强调一个类能否被克隆。如下是一个橘子(Orange)类的示例:
public class Orange implements Cloneable {
private String name;
private Double weight;
public Orange(String name, Double weight) {
this.name = name;
this.weight = weight;
}
public String getName() {
return name;
}
public Double getWeight() {
return weight;
}
@Override
public Orange clone() throws CloneNotSupportedException {
return (Orange) super.clone();
}
}
如上例中,我们实现了 Cloneable 接口,并重写了 clone()
方法,没有特别的逻辑,直接调用了超类的 clone() 方法。
注意:如果要实现深拷贝,需要在重写的 clone()
方法中进行特定的逻辑实现。
使用 clone() 方法
我们可以通过如下方式来调用 clone() 方法:
Orange orange1 = new Orange("桔子", 0.3);
try {
Orange orange2 = orange1.clone();
System.out.println("orange1: " + orange1);
System.out.println("orange2: " + orange2);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
运行结果如下:
orange1: com.example.Orange@15db9742
orange2: com.example.Orange@6d06d69c
可以看到返回的两个对象的 hashcode 不同,说明这两个对象实际上是两份不同的副本。经过 clone() 之后,orange1 和 orange2 两个橘子类的实例相同,但内存地址不同,互相独立,修改 orange1 的属性不会影响 orange2。
其他注意事项
由于 Object 类的 clone() 方法访问限制比较高,我们在使用时,有另外的三种可以使用的 clone 方法,分别是:
- 浅拷贝;
- 深拷贝;
- 序列化拷贝。
在具体开发中,可以根据实际需要选择不同的拷贝方式。
示例说明
浅拷贝示例
浅拷贝的对象引用属性不进行克隆,新建对象中的属性引用与原始对象中的属性引用是相同的。如:
public class Apple implements Cloneable {
private String name;
private Double weight;
private Date date;
public Apple(String name, Double weight, Date date) {
this.name = name;
this.weight = weight;
this.date = date;
}
public String getName() {
return name;
}
public Double getWeight() {
return weight;
}
public Date getDate() {
return date;
}
@Override
public Apple clone() throws CloneNotSupportedException {
return (Apple) super.clone();
}
}
public class Cook {
public static void main(String[] args) {
try {
Apple apple1 = new Apple("红苹果", 0.5, new Date());
Apple apple2 = apple1.clone();
System.out.println("apple1: " + apple1);
System.out.println("apple2: " + apple2);
System.out.println("是否是同一对象: " + (apple1 == apple2));
System.out.println("apple1.name: " + apple1.getName());
System.out.println("apple2.name: " + apple2.getName());
System.out.println("是否是同一对象: " + (apple1.getName() == apple2.getName()));
System.out.println("apple1.date: " + apple1.getDate());
System.out.println("apple2.date: " + apple2.getDate());
System.out.println("是否是同一对象: " + (apple1.getDate() == apple2.getDate()));
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
运行结果如下:
apple1: com.example.Apple@15db9742
apple2: com.example.Apple@6d06d69c
是否是同一对象: false
apple1.name: 红苹果
apple2.name: 红苹果
是否是同一对象: true
apple1.date: Thu Nov 19 14:22:14 CST 2020
apple2.date: Thu Nov 19 14:22:14 CST 2020
是否是同一对象: true
深拷贝示例
深拷贝是指完全克隆一个对象,即属性引用与原始对象中的属性引用不是相同的,而是新建的。如:
public class Banana implements Cloneable {
private String name;
private Double weight;
private Orange orange;
public Banana(String name, Double weight, Orange orange) {
this.name = name;
this.weight = weight;
this.orange = orange;
}
public String getName() {
return name;
}
public Double getWeight() {
return weight;
}
public Orange getOrange() {
return orange;
}
@Override
public Banana clone() throws CloneNotSupportedException {
Banana banana = (Banana) super.clone();
banana.orange = orange.clone();
return banana;
}
}
public class Cook {
public static void main(String[] args) {
try {
Orange orange = new Orange("桔子", 0.3);
Banana banana1 = new Banana("香蕉", 0.2, orange);
Banana banana2 = banana1.clone();
System.out.println("banana1: " + banana1);
System.out.println("banana2: " + banana2);
System.out.println("是否是同一对象: " + (banana1 == banana2));
System.out.println("banana1.orange: " + banana1.getOrange());
System.out.println("banana2.orange: " + banana2.getOrange());
System.out.println("是否是同一对象: " + (banana1.getOrange() == banana2.getOrange()));
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
运行结果如下:
banana1: com.example.Banana@15db9742
banana2: com.example.Banana@6d06d69c
是否是同一对象: false
banana1.orange: com.example.Orange@7852e922
banana2.orange: com.example.Orange@4e515669
是否是同一对象: false
序列化拷贝示例
使用序列化拷贝可以将对象进行二进制序列化,然后再将序列化后的二进制数据反序列化为一个新的对象。如:
public class Watermelon implements Serializable {
private String name;
private Double weight;
public Watermelon(String name, Double weight) {
this.name = name;
this.weight = weight;
}
public String getName() {
return name;
}
public Double getWeight() {
return weight;
}
}
public class Cook {
public static void main(String[] args) {
Watermelon watermelon1 = new Watermelon("西瓜", 5.0);
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(watermelon1);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
Watermelon watermelon2 = (Watermelon) ois.readObject();
System.out.println("watermelon1: " + watermelon1);
System.out.println("watermelon2: " + watermelon2);
System.out.println("是否是同一对象: " + (watermelon1 == watermelon2));
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
运行结果如下:
watermelon1: com.example.Watermelon@15db9742
watermelon2: com.example.Watermelon@6d06d69c
是否是同一对象: false
总结
以上就是Java中clone()
的使用方法,可以实现对象的拷贝功能。当然,使用时也要注意一些细节问题,根据实际场景选择对应的拷贝方式。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java 中clone()的使用方法 - Python技术站