java--浅拷贝深拷贝
1. 什么是拷贝?
在 Java 中,拷贝对象的过程可以分为两类:
浅拷贝(Shallow Copy)
仅复制对象本身的基本类型属性和引用类型的地址,不会复制引用对象本身。深拷贝(Deep Copy)
不仅复制对象本身,还会复制其引用类型所指向的对象,即完全复制一个“独立”的副本。
2. 浅拷贝(Shallow Copy)
📌 特点
基本数据类型 → 值被复制。
引用数据类型(对象、数组)→ 只复制引用地址,拷贝后的对象和原对象指向同一块内存。
修改引用对象的内容时,两个对象会同时变化。
📌 实现方式
实现
Cloneable
接口并重写clone()
方法(默认就是浅拷贝)。使用构造方法赋值(只复制属性,不做深层次复制)。
📌 示例
class Address {String city;Address(String city) {this.city = city;} }class Person implements Cloneable {String name;int age;Address address;Person(String name, int age, Address address) {this.name = name;this.age = age;this.address = address;}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone(); // 默认浅拷贝} }public class ShallowCopyDemo {public static void main(String[] args) throws Exception {Address addr = new Address("Beijing");Person p1 = new Person("Tom", 20, addr);Person p2 = (Person) p1.clone();System.out.println(p1.address.city); // BeijingSystem.out.println(p2.address.city); // Beijingp2.address.city = "Shanghai"; System.out.println(p1.address.city); // Shanghai(浅拷贝影响了原对象)} }
3. 深拷贝(Deep Copy)
📌 特点
基本数据类型 → 值被复制。
引用数据类型 → 会复制引用对象本身,两个对象完全独立。
修改副本对象不会影响原始对象。
📌 实现方式
手动实现深拷贝
在clone()
中,除了调用super.clone()
,还对引用对象进行手动clone
。序列化与反序列化
把对象写到流中,再读出来,就会得到一份新的对象,属于完全深拷贝。使用第三方工具库(如 Apache Commons Lang 的
SerializationUtils.clone()
)。
📌 示例1:手动深拷贝
class Address implements Cloneable {String city;Address(String city) {this.city = city;}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();} }class Person implements Cloneable {String name;int age;Address address;Person(String name, int age, Address address) {this.name = name;this.age = age;this.address = address;}@Overrideprotected Object clone() throws CloneNotSupportedException {Person cloned = (Person) super.clone();cloned.address = (Address) address.clone(); // 手动克隆引用对象return cloned;} }public class DeepCopyDemo1 {public static void main(String[] args) throws Exception {Address addr = new Address("Beijing");Person p1 = new Person("Tom", 20, addr);Person p2 = (Person) p1.clone();p2.address.city = "Shanghai";System.out.println(p1.address.city); // Beijing(深拷贝互不影响)System.out.println(p2.address.city); // Shanghai} }
📌 示例2:序列化深拷贝
import java.io.*;class Address implements Serializable {String city;Address(String city) { this.city = city; } }class Person implements Serializable {String name;int age;Address address;Person(String name, int age, Address address) {this.name = name;this.age = age;this.address = address;} }public class DeepCopyDemo2 {public static void main(String[] args) throws Exception {Address addr = new Address("Beijing");Person p1 = new Person("Tom", 20, addr);// 序列化 → 字节数组ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(bos);oos.writeObject(p1);// 反序列化 → 新对象ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());ObjectInputStream ois = new ObjectInputStream(bis);Person p2 = (Person) ois.readObject();p2.address.city = "Shanghai";System.out.println(p1.address.city); // BeijingSystem.out.println(p2.address.city); // Shanghai} }
4. 浅拷贝 vs 深拷贝 对比表
特性 浅拷贝 深拷贝 基本类型 拷贝值 拷贝值 引用类型 拷贝引用地址 拷贝新对象 是否独立 否,共享引用对象 是,完全独立 实现方式 Object.clone()
默认手动 clone / 序列化 / 工具库 性能 较快 较慢(需要额外复制引用对象) 使用场景 只需要复制对象本身,不关心引用对象 必须保证副本和原对象互不影响
5. 总结
浅拷贝:复制对象时,引用对象仍然共享,修改会互相影响。
深拷贝:复制对象时,引用对象也会被复制,完全独立。
实现方式:
浅拷贝:
clone()
默认实现深拷贝:手动
clone()
引用对象 / 序列化反序列化 / 工具类👉 一般情况下,如果对象中包含复杂的引用关系(如数组、集合、对象嵌套),推荐使用 深拷贝。