当前位置: 首页 > news >正文

java--浅拷贝深拷贝

1. 什么是拷贝?

在 Java 中,拷贝对象的过程可以分为两类:

  • 浅拷贝(Shallow Copy)
    仅复制对象本身的基本类型属性引用类型的地址,不会复制引用对象本身。

  • 深拷贝(Deep Copy)
    不仅复制对象本身,还会复制其引用类型所指向的对象,即完全复制一个“独立”的副本。


2. 浅拷贝(Shallow Copy)

📌 特点

  • 基本数据类型 → 值被复制。

  • 引用数据类型(对象、数组)→ 只复制引用地址,拷贝后的对象和原对象指向同一块内存。

  • 修改引用对象的内容时,两个对象会同时变化。

📌 实现方式

  1. 实现 Cloneable 接口并重写 clone() 方法(默认就是浅拷贝)。

  2. 使用构造方法赋值(只复制属性,不做深层次复制)。

📌 示例

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)

📌 特点

  • 基本数据类型 → 值被复制。

  • 引用数据类型 → 会复制引用对象本身,两个对象完全独立。

  • 修改副本对象不会影响原始对象。

📌 实现方式

  1. 手动实现深拷贝
    clone() 中,除了调用 super.clone(),还对引用对象进行手动 clone

  2. 序列化与反序列化
    把对象写到流中,再读出来,就会得到一份新的对象,属于完全深拷贝。

  3. 使用第三方工具库(如 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() 引用对象 / 序列化反序列化 / 工具类

👉 一般情况下,如果对象中包含复杂的引用关系(如数组、集合、对象嵌套),推荐使用 深拷贝

http://www.dtcms.com/a/360212.html

相关文章:

  • Introduction to GIS —— Chapter 3(Vector Data Model)
  • 雪花算法生成分布式ID
  • AI 智能体汇总,自动执行任务的“真 Agent”
  • 动态规划入门(三):一些经典动态规划模型
  • 赵玉平《刘备谋略》读书笔记(下部)
  • 小迪自用web笔记22
  • 01背包day35
  • 设计模式 | 常见的设计模式(单例、工厂、代理、适配器、责任链等等)
  • VisionProC#联合编程火花塞距离检测与VisionPro操作
  • libmodbus库,c++配置方法
  • 【CUDA入门·Lesson 1】Ubuntu实战:CUDA 概念、nvidia-smi 工具与 GPU 参数详解
  • 在Unity中,让子物体不随父物体移动或转动的方法!
  • 下一代防火墙(NGFW):从定义到功能
  • 试试 Xget 加速 GitHub 克隆仓库
  • 【WEB】[BUUCTF] <GXYCTF2019禁止套娃>《php函数的运用》
  • 大模型RAG项目实战:向量数据库Faiss
  • 【初始web3】什么是web3
  • 大模型时代:用Redis构建百亿级向量数据库方
  • 【自记】 Python 中函数参数前加 *(单星号)的解包可迭代对象写法说明
  • OpenCL C 内存对象
  • 第2.5节:中文大模型(文心一言、通义千问、讯飞星火)
  • 在线图片特效工具,600种创意模板
  • Python入门教程:常用第三方库Matplotlib(基本用法)下载、安装、参数解析教程
  • 案例——从零开始搭建 ASP.NET Core 健康检查实例
  • 【MLLM】语音端到端大模型和Voice Agent发展
  • 【Java进阶】Java与SpringBoot线程池深度优化指南
  • GitHub 热榜项目 - 日榜(2025-08-31)
  • 【AI编程工具】使用Cursor快速搭建一套小型项目管理系统
  • mysql5.7.44安装遇到登录权限问题
  • 在Linux环境安装Maven(保姆级别)