2026/6/9 12:07:20
网站建设
项目流程
合水口网站建设,建设企业网站中国建设银行,建设网站图片大全,网站建设需要什么程序员目录
作者有话要说
一#xff0c;数据类型
二#xff0c;浅拷贝的介绍
三#xff0c;浅拷贝的代码实现
四#xff0c;浅拷贝和赋值的区别
五#xff0c;深拷贝的介绍
六#xff0c;深拷贝的代码实现
方式 1#xff1a;重写clone()方法#xff0c;手动克隆引用属…目录作者有话要说一数据类型二浅拷贝的介绍三浅拷贝的代码实现四浅拷贝和赋值的区别五深拷贝的介绍六深拷贝的代码实现方式 1重写clone()方法手动克隆引用属性推荐方式 2通过序列化实现深拷贝适合复杂引用类型七深拷贝和浅拷贝的对比作者有话要说本文深入讲解赋值、深拷贝和浅拷贝的概念并画了详细的内存示意图帮助大家理解。如果有条件建议大家可以运行示例代码观察运行结果可以更加深入的理解。一数据类型想要了解什么是深拷贝和浅拷贝我们先来了解一下数据类型数据类型分为基本数据类型和引用类型八大基本数据类型byteshortintlongchardoublefloutboolean引用类型除去八大基本类型外所有数据类型都属于引用类型。例如string数组。基本数据类型在定义的时候是将值直接存储在栈内存中。引用类型在定义的时候是将数据存放在堆内存中然后在栈中存储了指针该指针指向堆中该实体的起始地址。二浅拷贝的介绍定义只拷贝“表面”共享引用基本数据类型拷贝属性的值新对象和老对象互不影响。引用类型拷贝属性的引用地址新对象和老对象共享同一个堆内存中的实际对象。从图中可以看出来浅拷贝是拷贝了一个新对象但是他的指针还是指向堆内存的easy。也就是说a改变或者a(浅拷贝)的改变都会引起easy的变化。直观示意图原型对象Resume ├── 基本属性name 张三栈内存值 ├── 基本属性job Java开发栈内存值 └── 引用属性workExperience栈内存地址0x123→ 堆内存WorkExperience对象period2020-2025, company某公司 浅拷贝后的新对象Resume Clone ├── 基本属性name 张三栈内存新值独立 ├── 基本属性job 大数据开发栈内存新值独立 └── 引用属性workExperience栈内存地址0x123→ 堆内存同一个WorkExperience对象共享优点实现简单、效率高仅拷贝值和引用无需递归处理缺点引用类型属性共享修改克隆对象的引用属性会影响原型对象破坏数据独立性。三浅拷贝的代码实现第一步实现cloneable接口。第二步重写clone方法。class Resume implements Cloneable { // 基本数据类型 private String name; private String job; // 引用数据类型 private WorkExperience workExperience; public Resume(String name) { this.name name; this.workExperience new WorkExperience(2020-2025, 某科技公司); } // 重写clone方法默认浅拷贝 Override protected Resume clone() { try { return (Resume) super.clone(); } catch (CloneNotSupportedException e) { throw new RuntimeException(e); } } // 内部引用类 static class WorkExperience { private String period; private String company; public WorkExperience(String period, String company) { this.period period; this.company company; } // getter/setter public String getPeriod() { return period; } public String getCompany() { return company; } public void setCompany(String company) { this.company company; } } // 测试浅拷贝的问题 public static void main(String[] args) { Resume prototype new Resume(张三); Resume clone prototype.clone(); // 修改克隆对象的引用属性 clone.workExperience.setCompany(某互联网公司); // 原型对象的引用属性也被修改了 System.out.println(prototype.workExperience.getCompany()); // 输出某互联网公司 } }四浅拷贝和赋值的区别赋值和浅拷贝都涉及 “对象的复用”但二者的本质完全不同 ——赋值是 “引用传递”浅拷贝是 “创建新对象 部分属性拷贝”核心区别体现在对象的独立性上。举个例子只考虑引用数据类型的情况赋值就是给你自己改一个名字你自身对象还是你自己没有变你的母亲引用地址还是你的母亲。浅拷贝就是给你复制了一个克隆的双胞胎兄弟姐妹双胞胎兄弟姐妹是一个新的个体但是你们两个人的生理上的母亲引用地址还是你的母亲而且你们两个长得也是一样的。二者对比图五深拷贝的介绍定义拷贝“全部”完全独立基本数据类型拷贝属性的值。引用类型递归拷贝引用指向的实际对象。从图中可以看出来堆内存中深拷贝了一个新的对象a深拷贝并且堆内存中的easy也被拷贝了一份也就是a对easy的改变并不会影响a深拷贝指向的easy。直观示意图原型对象Resume ├── 基本属性name 张三 ├── 基本属性job Java开发 └── 引用属性workExperience地址0x123→ 堆内存WorkExperience对象A 深拷贝后的新对象Resume Clone ├── 基本属性name 张三 ├── 基本属性job 大数据开发 └── 引用属性workExperience地址0x456→ 堆内存WorkExperience对象B和A内容一样地址不同优点新对象与原型对象完全独立修改一方不会影响另一方数据安全性高缺点实现复杂尤其是多层引用类型、效率较低递归拷贝或序列化需要额外开销。六深拷贝的代码实现方式 1重写clone()方法手动克隆引用属性推荐class Resume implements Cloneable { private String name; private String job; private WorkExperience workExperience; public Resume(String name) { this.name name; this.workExperience new WorkExperience(2020-2025, 某科技公司); } // 重写clone方法实现深拷贝 Override protected Resume clone() { try { Resume clone (Resume) super.clone(); // 手动克隆引用类型属性递归拷贝 clone.workExperience this.workExperience.clone(); return clone; } catch (CloneNotSupportedException e) { throw new RuntimeException(e); } } // 引用类也实现Cloneable static class WorkExperience implements Cloneable { private String period; private String company; public WorkExperience(String period, String company) { this.period period; this.company company; } // 重写clone方法 Override protected WorkExperience clone() throws CloneNotSupportedException { return (WorkExperience) super.clone(); } // getter/setter public String getPeriod() { return period; } public String getCompany() { return company; } public void setCompany(String company) { this.company company; } } // 测试深拷贝 public static void main(String[] args) { Resume prototype new Resume(张三); Resume clone prototype.clone(); clone.workExperience.setCompany(某互联网公司); // 原型对象的引用属性不受影响 System.out.println(prototype.workExperience.getCompany()); // 输出某科技公司 System.out.println(clone.workExperience.getCompany()); // 输出某互联网公司 } }方式 2通过序列化实现深拷贝适合复杂引用类型序列化是将对象转化为字节流反序列化是将字节流还原为新对象这个过程会自动创建全新的对象包括所有引用类型。要求所有涉及的类都实现Serializable接口。import java.io.*; class Resume implements Serializable { private static final long serialVersionUID 1L; private String name; private String job; private WorkExperience workExperience; // 该类也需实现Serializable public Resume(String name) { this.name name; this.workExperience new WorkExperience(2020-2025, 某科技公司); } // 深拷贝方法序列化反序列化 public Resume deepClone() { try ( ByteArrayOutputStream bos new ByteArrayOutputStream(); ObjectOutputStream oos new ObjectOutputStream(bos); ) { // 序列化对象 oos.writeObject(this); // 反序列化生成新对象 try ( ByteArrayInputStream bis new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream ois new ObjectInputStream(bis); ) { return (Resume) ois.readObject(); } } catch (IOException | ClassNotFoundException e) { throw new RuntimeException(e); } } static class WorkExperience implements Serializable { private static final long serialVersionUID 1L; private String period; private String company; // 构造器getter/setter public WorkExperience(String period, String company) { this.period period; this.company company; } public String getPeriod() { return period; } public String getCompany() { return company; } public void setCompany(String company) { this.company company; } } // 测试 public static void main(String[] args) { Resume prototype new Resume(张三); Resume clone prototype.deepClone(); clone.workExperience.setCompany(某互联网公司); System.out.println(prototype.workExperience.getCompany()); // 输出某科技公司 } }七深拷贝和浅拷贝的对比