总结
- 引用拷贝:复制对象引用地址,新旧变量指向同一对象。
- 浅拷贝:创建新对象,复制基本类型值,引用类型仍指向原对象。
- 深拷贝:完全复制对象及关联的所有子对象,新旧对象完全独立。
- 实现方式:浅拷贝常用clone()方法(需重写),深拷贝需递归复制或序列化实现。
- 核心区别:深拷贝隔离数据修改,浅拷贝和引用拷贝存在数据关联性。
详细解析
在 Java 中,深拷贝(Deep Copy)、浅拷贝(Shallow Copy) 和 引用拷贝(Reference Copy) 是对象复制的三种不同方式,它们的核心区别在于对对象及其内部数据的复制深度。以下是它们的详细对比和实现方式:
一、核心概念对比
类型 | 定义 | 特点 | 示例 |
---|---|---|---|
引用拷贝 | 两个变量指向同一个堆内存对象(本质是引用的赋值) | 修改任意变量会影响另一个变量 | Person p1 = new Person(); Person p2 = p1; |
浅拷贝 | 创建一个新对象,并复制原对象的字段值(基本类型复制值,引用类型复制地址) | 新对象与原对象共享内部引用类型字段的实例 | Person p2 = p1.clone(); (未深拷贝内部的Address对象) |
深拷贝 | 创建一个新对象,并递归复制所有内部引用对象的字段值 | 新对象与原对象完全独立,不共享任何引用类型字段的实例 | Person p2 = p1.deepClone(); (内部Address对象也被复制) |
二、具体实现与示例
1. 引用拷贝(Reference Copy)
-
本质:多个引用指向同一对象,没有创建新对象。
-
代码示例:
1
2
3
4
5
Person p1 =
new
Person(
"Alice"
,
new
Address(
"北京"
));
Person p2 = p1;
// 引用拷贝
p2.setName(
"Bob"
);
System.out.println(p1.getName());
// 输出 "Bob"(共享同一对象)
2. 浅拷贝(Shallow Copy)
-
实现方式:实现Cloneable接口,重写clone()方法。
-
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class
Person
implements
Cloneable {
private
String name;
private
Address address;
@Override
public
Person clone()
throws
CloneNotSupportedException {
return
(Person)
super
.clone();
// 默认浅拷贝(address 字段共享)
}
}
// 测试
Person p1 =
new
Person(
"Alice"
,
new
Address(
"北京"
));
Person p2 = p1.clone();
p2.getAddress().setCity(
"上海"
);
System.out.println(p1.getAddress().getCity());
// 输出 "上海"(共享 address 对象)
3. 深拷贝(Deep Copy)
-
实现方式:递归复制所有引用类型字段。
-
实现示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class
Address
implements
Cloneable {
private
String city;
@Override
public
Address clone()
throws
CloneNotSupportedException {
return
(Address)
super
.clone();
}
}
class
Person
implements
Cloneable {
private
String name;
private
Address address;
@Override
public
Person clone()
throws
CloneNotSupportedException {
Person cloned = (Person)
super
.clone();
cloned.address =
this
.address.clone();
// 深拷贝 address 对象
return
cloned;
}
}
// 测试
Person p1 =
new
Person(
"Alice"
,
new
Address(
"北京"
));
Person p2 = p1.clone();
p2.getAddress().setCity(
"上海"
);
System.out.println(p1.getAddress().getCity());
// 输出 "北京"(address 对象独立)
三、关键区别总结
特性 | 引用拷贝 | 浅拷贝 | 深拷贝 |
---|---|---|---|
对象独立性 | 完全共享同一对象 | 对象独立,但内部引用共享 | 对象及内部引用均独立 |
内存开销 | 无额外开销 | 仅复制外层对象 | 递归复制所有引用对象 |
实现复杂度 | 直接赋值即可 | 需实现Cloneable接口 | 需递归处理所有引用类型字段 |
典型应用场景 | 临时引用共享 | 对象结构简单(无嵌套可变引用) | 对象结构复杂(需完全独立) |