深拷贝|浅拷贝

深拷贝|浅拷贝深拷贝 浅拷贝 深拷贝和浅拷贝

大家好,欢迎来到IT知识分享网。

目录

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;   } ​    @Override    protected 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 York        System.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 York        System.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   } } ​

总结

  • 浅拷贝深拷贝分别适用于不同的场景。
  • 根据需要选择合适的拷贝方法,并利用现有的框架和库简化工作。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/112163.html

(0)
上一篇 2026-01-20 11:16
下一篇 2026-01-20 11:26

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信