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

深拷贝|浅拷贝

目录

1. 深拷贝(Deep Copy)

2. 浅拷贝(Shallow Copy)

3. 深拷贝和浅拷贝的区别

4. 示例代码

浅拷贝示例

深拷贝示例

5.常用的方法

1.Java Object.clone() 方法

2.序列化与反序列化

6.Spring Boot 中的常用方法

使用 SerializationUtils

使用 ModelMapper 或 MapStruct

7.Hutool 工具类

浅拷贝

深拷贝

8.Guava 中的相关工具类

总结


深拷贝和浅拷贝是对象复制的两种方式,它们在处理引用类型的字段时存在显著差异。下面将详细介绍它们的含义、区别,并提供代码示例。

1. 深拷贝(Deep Copy)

  • 定义:深拷贝创建一个新对象,并且复制原对象中的所有字段,包括引用类型的字段。对于每个引用类型的字段,它都会创建一个新的实例,确保源对象和目标对象之间没有任何共享的引用。

    • 递归地复制所有子对象。即使原始对象或拷贝对象修改其子对象,也不会互相影响。

  • 特点

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

    • 引用数据类型的对象会被完全独立地复制。

2. 浅拷贝(Shallow Copy)

  • 定义:浅拷贝创建一个新对象,该对象与原对象具有相同的值,但对引用类型字段只会复制引用地址,而不复制实际的对象。这意味着原对象和新对象的引用类型属性指向同一块内存。

    • 不递归地复制对象所引用的子对象。它仅复制对象的基本数据类型和对引用类型的引用,因此原始对象和拷贝对象中对引用类型的修改会相互影响。

  • 特点

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

    • 引用数据类型的对象会共享同一个实例。

3. 深拷贝和浅拷贝的区别

特性浅拷贝深拷贝
对基本类型复制其值复制其值
对引用类型复制引用(共同使用同一对象)复制对象(各自独立的对象)
影响修改一个对象的引用类型字段会影响另一个对象修改一个对象不会影响另一个对象

4. 示例代码

浅拷贝示例
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;}
​@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone(); // 浅拷贝}
}
​
public class ShallowCopyExample {public static void main(String[] args) throws CloneNotSupportedException {Address address = new Address("New York");Person person1 = new Person("Alice", address);Person person2 = (Person) person1.clone(); // 浅拷贝
​System.out.println("Before modification:");System.out.println("Person1 Address: " + person1.address.city); // 输出: New YorkSystem.out.println("Person2 Address: " + person2.address.city); // 输出: New York
​// 修改 person2 的地址person2.address.city = "Los Angeles";
​System.out.println("After modification:");System.out.println("Person1 Address: " + person1.address.city); // 输出: Los Angeles (共享同一引用)System.out.println("Person2 Address: " + person2.address.city); // 输出: Los Angeles}
}
深拷贝示例
class Address {String city;
​public Address(String city) {this.city = city;}
​// 深拷贝方法public Address deepCopy() {return new Address(this.city);}
}
​
class Person {String name;Address address;
​public Person(String name, Address address) {this.name = name;this.address = address;}
​// 深拷贝方法public Person deepCopy() {return new Person(this.name, this.address.deepCopy());}
}
​
public class DeepCopyExample {public static void main(String[] args) {Address address = new Address("New York");Person person1 = new Person("Alice", address);Person person2 = person1.deepCopy(); // 深拷贝
​System.out.println("Before modification:");System.out.println("Person1 Address: " + person1.address.city); // 输出: New YorkSystem.out.println("Person2 Address: " + person2.address.city); // 输出: New York
​// 修改 person2 的地址person2.address.city = "Los Angeles";
​System.out.println("After modification:");System.out.println("Person1 Address: " + person1.address.city); // 输出: New York (不受影响)System.out.println("Person2 Address: " + person2.address.city); // 输出: Los Angeles}
}

5.常用的方法

1.Java Object.clone() 方法
  • Object 类提供的 clone() 方法可以用于实现浅拷贝。

  • 需要实现 Cloneable 接口,并重写 clone() 方法。

2.序列化与反序列化
  • 对象可以通过序列化为字节流,再反序列化为新对象。这种方式可以实现深拷贝。

  • 需要实现 Serializable 接口。

6.Spring Boot 中的常用方法

在 Spring Boot 中,通常使用以下方式来实现深拷贝:

使用 SerializationUtils
import org.springframework.util.SerializationUtils;
​
byte[] bytes = SerializationUtils.serialize(originalObject);
MyObject copiedObject = (MyObject) SerializationUtils.deserialize(bytes);
使用 ModelMapper 或 MapStruct

ModelMapperMapStruct 都可以用来轻松地进行对象之间的映射,借此实现深拷贝。

7.Hutool 工具类

Hutool 提供了简单易用的工具类,可以进行深拷贝和浅拷贝:

浅拷贝
Person copy = ShallowUtil.clone(original);
深拷贝
Person deepCopy = CloneUtil.clone(original);

8.Guava 中的相关工具类

Guava 提供了 Immutable 集合来避免可变性,虽然不是直接的拷贝方法,但可以帮助管理不可变对象。

  • ImmutableListImmutableSetImmutableMap 用于创建不可变的集合,这样可以避免浅拷贝的问题。

  • 不可变集合在创建后无法更改,这使得它们特别适合于多线程环境和函数式编程风格。

import com.google.common.collect.ImmutableList;
​
public class ImmutableListExample {public static void main(String[] args) {// 创建一个不可变列表ImmutableList<String> immutableList = ImmutableList.of("Apple", "Banana", "Cherry");
​System.out.println(immutableList);
​// 下面的操作会抛出 UnsupportedOperationException,因为该列表是不可变的// immutableList.add("Date"); // Uncommenting this line will throw an exception}
}
import com.google.common.collect.ImmutableSet;
​
public class ImmutableSetExample {public static void main(String[] args) {// 创建一个不可变集合ImmutableSet<String> immutableSet = ImmutableSet.of("Red", "Green", "Blue");
​System.out.println(immutableSet);
​// 下面的操作会抛出 UnsupportedOperationException,因为该集合是不可变的// immutableSet.add("Yellow"); // Uncommenting this line will throw an exception}
}
​
​
import com.google.common.collect.ImmutableMap;
​
public class ImmutableMapExample {public static void main(String[] args) {// 创建一个不可变映射ImmutableMap<String, Integer> immutableMap = ImmutableMap.of("Alice", 30,"Bob", 25,"Charlie", 35);
​System.out.println(immutableMap);
​// 下面的操作会抛出 UnsupportedOperationException,因为该映射是不可变的// immutableMap.put("Dave", 40); // Uncommenting this line will throw an exception}
}
​

总结

  • 浅拷贝深拷贝分别适用于不同的场景。

  • 根据需要选择合适的拷贝方法,并利用现有的框架和库简化工作。

http://www.lryc.cn/news/441508.html

相关文章:

  • 图像处理-掩码
  • [2025]基于微信小程序慢性呼吸系统疾病的健康管理(源码+文档+解答)
  • react之jsx基础(1)概念和本质
  • sqli-labs靶场自动化利用工具——第13关
  • 大舍传媒:尼日利亚传统新闻媒体宣传助力新兴行业蓬勃发展
  • ISSTA 2024盛大开幕:中国学者的录取数和投稿量均位列第一
  • HttpMediaTypeNotAcceptableException: No acceptable representation问题解决方法
  • Scrapy爬虫框架 Pipeline 数据传输管道
  • vim的 配置文件
  • Golang | Leetcode Golang题解之第403题青蛙过河
  • 前端项目使用js将dom生成图片、PDF
  • 在 Red Hat 上安装 SQL Server 2022 并创建数据库
  • 游戏如何应对云手机刷量问题
  • QTableView使用QSortFilterProxyModel后行号错乱
  • 【Python】 报错Can‘t find model ‘en_core_web_md‘
  • 每天五分钟深度学习框架pytorch:pytorch中已经定义好的损失函数
  • dedecms(四种webshell姿势)、aspcms webshell漏洞复现
  • 【STM32系统】基于STM32设计的智能垃圾桶(语音、颜色识别、称重、光强、烟雾、人体识别、步进电机、水泵)——文末资料下载
  • GPT代码记录
  • powerbi
  • 【Unity】检测鼠标点击位置是否有2D对象
  • Python学习——【2.1】if语句相关语法
  • 机器学习--K-Means
  • 模型训练时CPU和GPU大幅度波动——可能是数据的读入拖后腿
  • keep-alive的应用场景
  • 【C++ Primer Plus习题】16.9
  • Java入门:09.Java中三大特性(封装、继承、多态)02
  • AI为云游戏带来的革新及解决方案:深度技术剖析与未来展望
  • 集合是什么
  • JavaDS —— 图