📌 专栏 :大白话说Java面试题 --- 01-Java基础篇
第40题:Java中的深拷贝和浅拷贝有什么区别
📚 回答:
- 核心概念 :
深拷贝和浅拷贝是 Java 中对象复制的两种方式,主要区别在于是否复制对象内部的引用类型成员变量。
1. 浅拷贝
-
定义:
- 浅拷贝只复制对象本身,而不复制对象内部的引用类型成员变量。
- 复制后的对象和原对象共享引用类型的成员变量。
-
实现方式:
- 实现
Cloneable接口并重写clone()方法。 - 默认的
clone()方法执行的是浅拷贝。
💡 代码示例 :
以下代码展示了浅拷贝的行为:
- 实现
java
class Address {
String city;
public Address(String city) {
this.city = city;
}
}
class Person implements Cloneable {
String name;
Address address;
public Person(String name, Address address) {
this.name = name;
this.address = address;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone(); // 默认浅拷贝
}
}
public class Main {
public static void main(String[] args) throws CloneNotSupportedException {
Address address = new Address("Beijing");
Person p1 = new Person("Alice", address);
Person p2 = (Person) p1.clone();
p2.address.city = "Shanghai";
System.out.println(p1.address.city); // 输出 Shanghai
}
}
2. 深拷贝
-
定义:
- 深拷贝不仅复制对象本身,还递归地复制对象内部的所有引用类型成员变量。
- 复制后的对象和原对象完全独立,互不影响。
-
实现方式:
- 在
clone()方法中手动复制引用类型成员变量。 - 或者通过序列化(
Serializable)实现深拷贝。
💡 代码示例 :
以下代码展示了深拷贝的行为:
- 在
java
class Address implements Cloneable {
String city;
public Address(String city) {
this.city = city;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Person implements Cloneable {
String name;
Address address;
public Person(String name, Address address) {
this.name = name;
this.address = address;
}
@Override
protected Object clone() throws CloneNotSupportedException {
Person cloned = (Person) super.clone();
cloned.address = (Address) address.clone(); // 深拷贝引用类型
return cloned;
}
}
public class Main {
public static void main(String[] args) throws CloneNotSupportedException {
Address address = new Address("Beijing");
Person p1 = new Person("Alice", address);
Person p2 = (Person) p1.clone();
p2.address.city = "Shanghai";
System.out.println(p1.address.city); // 输出 Beijing
}
}
3. 对比总结
| 特性 | 浅拷贝 | 深拷贝 |
|---|---|---|
| 复制范围 | 只复制对象本身 | 复制对象及其所有引用类型成员变量 |
| 实现方式 | 默认 clone() 方法 |
手动复制引用类型或序列化 |
| 适用场景 | 引用类型成员变量无需独立时 | 引用类型成员变量需要完全独立时 |
💡 面试官视角:
- 面试官可能会问"如何实现深拷贝?"答:可以通过手动复制引用类型成员变量或使用序列化(
Serializable)机制。 - 面试官可能会追问"浅拷贝有哪些局限性?"答:浅拷贝可能导致多个对象共享同一引用类型的成员变量,修改一个对象会影响其他对象。