1. 克隆的基本概念
- 浅克隆:复制对象的基本类型字段和引用,引用类型的字段仍指向原对象。通过
Object.clone()
默认实现。 - 深克隆:递归复制所有引用类型的字段,生成完全独立的副本。需手动实现。
2. 实现克隆的步骤
- 实现
Cloneable
接口:标记接口,表明该类允许克隆。 - 重写
clone()
方法: - 将访问修饰符改为public
。 - 调用super.clone()
初始化对象。
处理深克隆(如需)
public class Person implements Cloneable {
private String name;
private Address address; // 引用类型
@Override
public Person clone() {
try {
Person cloned = (Person) super.clone();
cloned.address = this.address.clone(); // 深克隆Address
return cloned;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
}
3. 深克隆的实现
- 引用类型的字段需自身实现
Cloneable
并重写clone()
。
public class Address implements Cloneable {
private String city;
@Override
public Address clone() {
try {
return (Address) super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
}
4. 注意事项
final
字段:无法通过克隆直接赋值,需使用构造方法或工厂方法。- 子类克隆:覆盖
clone()
时调用super.clone()
,并处理新增字段。 - 性能与复杂性:深克隆可能递归复制整个对象图,需权衡性能。
5. 替代方案
# 复制构造方法:更直观,避免Cloneable的复杂性。
public Person(Person other) {
this.name = other.name;
this.address = new Address(other.address);
}
# 序列化:实现Serializable接口,通过对象流深克隆。
public static <T extends Serializable> T deepClone(T obj) {
// 序列化与反序列化代码
}
6. 数组的克隆
数组默认支持浅克隆:
int[] arr = {1, 2, 3}; int[] clonedArr = arr.clone();
7. 最佳实践
- 谨慎使用
clone()
:推荐使用复制构造方法或工厂方法。 - 处理异常:将
CloneNotSupportedException
转换为非受检异常(如断言错误)。
Java的克隆机制通过Cloneable
和Object.clone()
实现,默认浅克隆,深克隆需手动处理。尽管灵活,但存在复杂性和设计缺陷。推荐优先使用复制构造方法或序列化实现对象复制,以提高代码可维护性和安全性。