手写一个深拷贝工具

server/2024/11/24 19:41:01/

背景

在面向对象编程中,对象之间的复制是一个常见的需求。对象的复制通常分为浅拷贝(Shallow Copy)和深拷贝(Deep Copy)两种方式。浅拷贝只复制对象的基本数据类型和引用类型的数据地址,而深拷贝则会递归地复制对象及其引用的所有子对象,确保新对象与原对象完全独立。

深拷贝的重要性在于它可以避免对象之间的相互影响。在实际开发中,如果不正确地处理对象的复制,可能会导致数据不一致、内存泄漏等问题。因此,掌握深拷贝的实现方法对于提高代码质量和系统稳定性具有重要意义。

深拷贝介绍

深拷贝(Deep Copy)是指在复制对象时,不仅复制对象本身,还递归地复制对象中引用的所有子对象。这样可以确保新对象与原对象完全独立,修改新对象不会影响原对象。

浅拷贝的不足

在 Java 中,如果我们简单地使用赋值语句将一个对象赋值给另一个对象,例如:

class Person {private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}// Getters and setters
}public class Main {public static void main(String[] args) {Person person1 = new Person("Alice", 25);Person person2 = person1;person2.setAge(30);System.out.println(person1.getAge()); // 输出 30,而不是 25}
}

这里,person2 只是 person1 的浅拷贝,它们指向同一个内存地址。当修改 person2 的属性时,person1 的属性也随之改变,因为它们本质上是同一个对象。

深拷贝的应用场景

  1. 多线程环境:在多线程环境中,为了避免多个线程对同一个对象的访问导致的数据不一致问题,可以使用深拷贝来创建独立的对象副本。
  2. 数据备份:在进行数据备份时,深拷贝可以确保备份数据与原始数据完全独立,避免因修改原始数据而影响备份数据。
  3. 历史记录:在需要保存对象的历史状态时,深拷贝可以创建对象的完整副本,以便后续回溯或恢复。
  4. 对象传递:在需要将对象传递给其他方法或模块时,使用深拷贝可以确保传递的是一个独立的副本,避免意外的修改影响原对象。

代码示例

下面是一个使用 Java 反射机制实现深拷贝的示例。这个示例展示了如何将一个复杂的对象深拷贝到另一个对象中,即使这两个对象是不同的类,但具有相同名称和类型的字段。

定义实体类


// 嵌套对象 A
public class NestedObjectA {private int id;private String name;// Getters and Setterspublic int getId() { return id; }public void setId(int id) { this.id = id; }public String getName() { return name; }public void setName(String name) { this.name = name; }@Overridepublic String toString() {return "NestedObjectA{" +"id=" + id +", name='" + name + '\'' +'}';}
}// 嵌套对象 B
public class NestedObjectB {private double value;private NestedObjectA nestedObjectA;// Getters and Setterspublic double getValue() { return value; }public void setValue(double value) { this.value = value; }public NestedObjectA getNestedObjectA() { return nestedObjectA; }public void setNestedObjectA(NestedObjectA nestedObjectA) { this.nestedObjectA = nestedObjectA; }@Overridepublic String toString() {return "NestedObjectB{" +"value=" + value +", nestedObjectA=" + nestedObjectA +'}';}
}// 源对象
public class SourceObject {private int intField;private String stringField;private List<NestedObjectA> listField;private Map<String, NestedObjectB> mapField;// Getters and Setterspublic int getIntField() { return intField; }public void setIntField(int intField) { this.intField = intField; }public String getStringField() { return stringField; }public void setStringField(String stringField) { this.stringField = stringField; }public List<NestedObjectA> getListField() { return listField; }public void setListField(List<NestedObjectA> listField) { this.listField = listField; }public Map<String, NestedObjectB> getMapField() { return mapField; }public void setMapField(Map<String, NestedObjectB> mapField) { this.mapField = mapField; }@Overridepublic String toString() {return "SourceObject{" +"intField=" + intField +", stringField='" + stringField + '\'' +", listField=" + listField +", mapField=" + mapField +'}';}
}// 目标对象
public class TargetObject {private int intField;private String stringField;private List<NestedObjectA> listField;private Map<String, NestedObjectB> mapField;// Getters and Setterspublic int getIntField() { return intField; }public void setIntField(int intField) { this.intField = intField; }public String getStringField() { return stringField; }public void setStringField(String stringField) { this.stringField = stringField; }public List<NestedObjectA> getListField() { return listField; }public void setListField(List<NestedObjectA> listField) { this.listField = listField; }public Map<String, NestedObjectB> getMapField() { return mapField; }public void setMapField(Map<String, NestedObjectB> mapField) { this.mapField = mapField; }@Overridepublic String toString() {return "TargetObject{" +"intField=" + intField +", stringField='" + stringField + '\'' +", listField=" + listField +", mapField=" + mapField +'}';}
}

DeepCopyUtil 深拷贝工具类

public class DeepCopyUtil {public static void deepCopyFields(Object source, Object target) throws IllegalAccessException {Class<?> sourceClass = source.getClass();Class<?> targetClass = target.getClass();// 获取源对象和目标对象的所有字段Field[] sourceFields = getAllFields(sourceClass);Field[] targetFields = getAllFields(targetClass);// 创建字段名称到字段的映射Map<String, Field> targetFieldMap = new HashMap<>();for (Field field : targetFields) {field.setAccessible(true);targetFieldMap.put(field.getName(), field);}// 遍历源对象的字段for (Field sourceField : sourceFields) {sourceField.setAccessible(true);Object sourceValue = sourceField.get(source);// 检查目标对象是否有同名字段Field targetField = targetFieldMap.get(sourceField.getName());if (targetField != null && sourceField.getType().equals(targetField.getType())) {if (isBasicTypeOrWrapperOrString(sourceField.getType())) {// 如果是基本类型或字符串,直接赋值给目标对象的对应字段targetField.set(target, sourceValue);} else if (List.class.isAssignableFrom(sourceField.getType())) {// 如果是列表类型,进行列表元素的深拷贝List<?> sourceList = (List<?>) sourceValue;List<Object> targetList = new ArrayList<>();for (Object item : sourceList) {targetList.add(deepCopy(item));}targetField.set(target, targetList);} else if (Set.class.isAssignableFrom(sourceField.getType())) {// 如果是集合类型,进行集合元素的深拷贝Set<?> sourceSet = (Set<?>) sourceValue;Set<Object> targetSet = new HashSet<>();for (Object item : sourceSet) {targetSet.add(deepCopy(item));}targetField.set(target, targetSet);} else if (Map.class.isAssignableFrom(sourceField.getType())) {// 如果是映射类型,进行映射元素的深拷贝Map<?, ?> sourceMap = (Map<?, ?>) sourceValue;Map<Object, Object> targetMap = new HashMap<>();for (Map.Entry<?, ?> entry : sourceMap.entrySet()) {Object key = deepCopy(entry.getKey());Object value = deepCopy(entry.getValue());targetMap.put(key, value);}targetField.set(target, targetMap);} else {// 其他类型进行深拷贝targetField.set(target, deepCopy(sourceValue));}}}}private static Field[] getAllFields(Class<?> clazz) {List<Field> fields = new ArrayList<>();while (clazz != null) {fields.addAll(Arrays.asList(clazz.getDeclaredFields()));clazz = clazz.getSuperclass();}return fields.toArray(new Field[0]);}private static boolean isBasicTypeOrWrapperOrString(Class<?> clazz) {return clazz.equals(int.class) || clazz.equals(Integer.class) ||clazz.equals(long.class) || clazz.equals(Long.class) ||clazz.equals(float.class) || clazz.equals(Float.class) ||clazz.equals(double.class) || clazz.equals(Double.class) ||clazz.equals(boolean.class) || clazz.equals(Boolean.class) ||clazz.equals(char.class) || clazz.equals(Character.class) ||clazz.equals(byte.class) || clazz.equals(Byte.class) ||clazz.equals(short.class) || clazz.equals(Short.class) ||clazz.equals(String.class);}private static Object deepCopy(Object obj) {if (obj == null) {return null;}if (isBasicTypeOrWrapperOrString(obj.getClass())) {return obj;}if (obj instanceof List) {List<?> sourceList = (List<?>) obj;List<Object> targetList = new ArrayList<>();for (Object item : sourceList) {targetList.add(deepCopy(item));}return targetList;}if (obj instanceof Set) {Set<?> sourceSet = (Set<?>) obj;Set<Object> targetSet = new HashSet<>();for (Object item : sourceSet) {targetSet.add(deepCopy(item));}return targetSet;}if (obj instanceof Map) {Map<?, ?> sourceMap = (Map<?, ?>) obj;Map<Object, Object> targetMap = new HashMap<>();for (Map.Entry<?, ?> entry : sourceMap.entrySet()) {Object key = deepCopy(entry.getKey());Object value = deepCopy(entry.getValue());targetMap.put(key, value);}return targetMap;}// 对于其他复杂对象,递归调用 deepCopyFields 方法try {Object target = obj.getClass().getDeclaredConstructor().newInstance();deepCopyFields(obj, target);return target;} catch (Exception e) {throw new RuntimeException("Failed to deep copy object", e);}}
}

Main方法

 public static void main(String[] args) throws IllegalAccessException {// 创建示例对象SourceObject source = new SourceObject();TargetObject target = new TargetObject();// 初始化源对象source.setIntField(10);source.setStringField("Hello");List<NestedObjectA> listField = new ArrayList<>();listField.add(new NestedObjectA());listField.get(0).setId(1);listField.get(0).setName("A1");source.setListField(listField);Map<String, NestedObjectB> mapField = new HashMap<>();NestedObjectB nestedObjectB = new NestedObjectB();nestedObjectB.setValue(3.14);nestedObjectB.setNestedObjectA(new NestedObjectA());nestedObjectB.getNestedObjectA().setId(2);nestedObjectB.getNestedObjectA().setName("A2");mapField.put("key1", nestedObjectB);source.setMapField(mapField);// 进行深拷贝deepCopyFields(source, target);// 输出结果System.out.println("Source: " + source);System.out.println("Target: " + target);}
}

http://www.ppmy.cn/server/144625.html

相关文章

React Native的`react-native-reanimated`库中的`useAnimatedStyle`钩子来创建一个动画样式

React Native的react-native-reanimated库中的useAnimatedStyle钩子来创建一个动画样式&#xff0c;用于一个滑动视图的每个项目&#xff08;SliderItem&#xff09;。useAnimatedStyle钩子允许你根据动画值&#xff08;在这个例子中是scrollX&#xff09;来动态地设置组件的样…

react和vue图片懒加载及实现原理

一、实现原理 核心思想&#xff1a; 只有当图片出现在视口中时&#xff0c;才加载图片。利用占位图或占位背景优化用户体验。 实现技术&#xff1a; 监听滚动事件&#xff1a;监听页面滚动&#xff0c;通过计算图片与视口的位置关系&#xff0c;判断是否需要加载图片。Intersec…

Scala学习记录,Array

数组&#xff1a;物理空间上连续的&#xff08;一个挨一个&#xff09;优势&#xff1a;根据下标能快速找到元素。 列表&#xff1a;物理空间上不连续&#xff08;不是一个元素挨着一个元素的&#xff09;优势&#xff1a;插入元素&#xff0c;删除较快。 Array定义&#xff…

大数据面试题每日练习--HDFS是如何工作的?

HDFS&#xff08;Hadoop Distributed File System&#xff09;是一个分布式文件系统&#xff0c;设计用于存储非常大的文件。它的主要工作原理如下&#xff1a; NameNode&#xff1a;管理文件系统的命名空间&#xff0c;维护文件目录树和文件元数据信息。NameNode记录每个文件…

一学就废|Python基础碎片,列表(List)

列表(数组)是一种常见的数据结构&#xff0c;通常&#xff0c;列表的共性操作包括获取、设置、搜索、过滤和排序。以下是对列表的一些常用的操作方法。 基本操作 我们可以在 Python 中操作列表的方法有很多。在我们开始学习这些通用操作之前&#xff0c;以下片段显示了列表最常…

[OpenHarmony5.0][Docker][环境]OpenHarmony5.0 Docker编译环境镜像下载以及使用方式

0. 制作过程 如果你想知道这个镜像是如何制作的&#xff0c;请看下面的教程&#xff0c;如果你只想拿到镜像。那就往下看就好了 链接&#xff1a; 1. 获取源码 源码下载请参考&#xff1a;OHOS_5.0中的[源码下载]章节&#xff0c;建议使用镜像站点下载。 2. 获取镜像 在Git…

【STM32】MPU6050初始化常用寄存器说明及示例代码

一、MPU6050常用配置寄存器 1、电源管理寄存器1&#xff08; PWR_MGMT_1 &#xff09; 此寄存器允许用户配置电源模式和时钟源。 DEVICE_RESET &#xff1a;用于控制复位的比特位。设置为1时复位 MPU6050&#xff0c;内部寄存器恢复为默认值&#xff0c;复位结束…

鸿蒙操作系统(HarmonyOS)开发的初学者了解和入门

1. 什么是鸿蒙操作系统&#xff08;HarmonyOS&#xff09; 鸿蒙操作系统是华为开发的一种分布式操作系统&#xff0c;面向多种设备&#xff08;如智能手机、智能家居设备、穿戴设备、车机等&#xff09;。它的特点包括&#xff1a; 分布式架构&#xff1a;支持跨设备无缝协作…