目录
浅拷贝(Shallow Copy)和深拷贝(Deep Copy)是对象复制的两种方式,主要区别在于对对象内部引用类型字段的处理方式不同。
- 浅拷贝:仅复制对象本身及其基本类型字段的值,对于引用类型字段,复制的是引用地址(即新对象和原对象共享同一块内存)。
- 深拷贝:完全复制对象及其所有字段(包括引用类型字段),新对象与原对象不共享任何内存,彼此独立。
一.Clonable接口
实现步骤:
①创建两个类
public class Test1 {
public static void main(String[] args) {
Person person1 = new Person(10,"zhangsan");
//Person person2 = person1.clone();//最开始点不出来
}
}
public class Person {
public int age;
public String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
②通过 person1 调用 Object类 的 clone 方法 会失败
③重写 Object类 的 clone 方法
( Alt+Insert → Generate → Override Methods → clone() )
④调用 重写 的 clone 方法 的返回值是Object类型,需要强转为(Person)
⑤现在运行会有一个异常
解决方法:
- throws CloneNotSupportedException ( 该内容在重写的clone()方法中 )
- 复制到main方法的后面
⑥现在代码虽然不会报错,但是还会有异常(不支持克隆)
解决方法:在person类 后面加上一个接口(标记接口)
完整代码:
public class Person implements Cloneable {
public int age;
public String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
@Override
protected Object clone()
throws CloneNotSupportedException {
return super.clone();
}
}
public class Test1 {
public static void main(String[] args)
throws CloneNotSupportedException {
Person person1 = new Person(10,"zhangsan");
Person person2 = (Person) person1.clone();//最开始点不出来
}
}
二.深拷贝
实现步骤:
①创建一个类,包含 Clonable接口 和 clone() 方法
public class Money implements Cloneable{
public double money = 9.9;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
并且在Person类中实例一个 Money对象 :m
原理:
- 通过改变 person2.m.money ,看 person1.m.money 是否被修改
- 如果改变 person2.m.money ,person1.m.money也被修改,那么就是浅拷贝,反之则为深拷贝
②再次重写Person类中的clone() 方法
protected Object clone()
throws CloneNotSupportedException {
//return super.clone();
Person tmp = (Person) super.clone();
tmp.m = (Money) this.m.clone();
return tmp;
}
③进行调试
public class Test1 {
public static void main(String[] args)
throws CloneNotSupportedException {
Person person1 = new Person(10,"zhangsan");
Person person2 = (Person) person1.clone();//最开始点不出来
System.out.println("修改前:"+person1.m.money);
System.out.println("修改前:"+person2.m.money);
person2.m.money = 99.99;
System.out.println("修改后:"+person1.m.money);
System.out.println("修改后:"+person2.m.money);
}
}
完整代码:
public class Test1 {
public static void main(String[] args)
throws CloneNotSupportedException {
Person person1 = new Person(10,"zhangsan");
Person person2 = (Person) person1.clone();//最开始点不出来
System.out.println("修改前:"+person1.m.money);
System.out.println("修改前:"+person2.m.money);
person2.m.money = 99.99;
System.out.println("修改后:"+person1.m.money);
System.out.println("修改后:"+person2.m.money);
}
}
public class Person implements Cloneable {
public int age;
public String name;
public Money m = new Money();
public Person(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
@Override
protected Object clone()
throws CloneNotSupportedException {
//return super.clone();
Person tmp = (Person) super.clone();
tmp.m = (Money) this.m.clone();
return tmp;
}
}
public class Money implements Cloneable{
public double money = 9.9;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
浅拷贝与深拷贝的对比
特性 | 浅拷贝 | 深拷贝 |
---|---|---|
复制范围 | 仅复制对象本身和基本类型字段 | 复制对象及其所有引用类型字段 |
内存占用 | 低(共享引用类型字段) | 高(完全独立) |
修改影响 | 修改引用类型字段会影响原对象 | 修改引用类型字段不影响原对象 |
实现复杂度 | 简单 | 复杂(需递归处理引用类型) |
使用场景建议
- 浅拷贝:适用于对象内部没有引用类型字段,或引用类型字段不可变(如
String
)。 - 深拷贝:适用于对象内部有可变引用类型字段,且需要完全独立副本的场景(如缓存、状态快照等)