在Java中,深度复制(Deep Copy)指的是创建一个对象的副本,这个副本与原始对象完全独立,修改副本不会影响原始对象。深度复制通常涉及到对象图中的所有对象,而不仅仅是对象本身。使用反射(Reflection)可以实现深度复制,但这种方法相对复杂且性能较低。
反射:Java反射机制允许程序在运行时检查和操作类、方法、字段等,通过反射API可以动态地创建对象、调用方法和访问字段。
深度复制:创建一个对象的副本,包括对象内部的所有嵌套对象,确保副本与原始对象完全独立。
类型:
应用场景:
以下是一个使用反射实现深度复制的示例代码:
import java.lang.reflect.Field;
import java.util.IdentityHashMap;
public class DeepCopyUtil {
public static Object deepCopy(Object original) throws Exception {
return deepCopy(original, new IdentityHashMap<>());
}
private static Object deepCopy(Object original, IdentityHashMap<Object, Object> visited) throws Exception {
if (original == null) {
return null;
}
// 检查是否已经复制过该对象
if (visited.containsKey(original)) {
return visited.get(original);
}
Class<?> clazz = original.getClass();
Object copy = clazz.getDeclaredConstructor().newInstance();
visited.put(original, copy);
for (Field field : clazz.getDeclaredFields()) {
field.setAccessible(true);
Object fieldValue = field.get(original);
if (fieldValue != null && !isPrimitiveOrWrapper(fieldValue.getClass()) && !fieldValue.getClass().isEnum()) {
fieldValue = deepCopy(fieldValue, visited);
}
field.set(copy, fieldValue);
}
return copy;
}
private static boolean isPrimitiveOrWrapper(Class<?> clazz) {
return clazz.isPrimitive() ||
clazz == Boolean.class ||
clazz == Character.class ||
clazz == Byte.class ||
clazz == Short.class ||
clazz == Integer.class ||
clazz == Long.class ||
clazz == Float.class ||
clazz == Double.class ||
clazz == String.class;
}
public static void main(String[] args) {
try {
// 示例对象
MyClass original = new MyClass();
original.setField1("Hello");
original.setField2(123);
MyClass copy = (MyClass) deepCopy(original);
System.out.println(copy.getField1()); // 输出: Hello
System.out.println(copy.getField2()); // 输出: 123
} catch (Exception e) {
e.printStackTrace();
}
}
}
class MyClass {
private String field1;
private int field2;
public String getField1() {
return field1;
}
public void setField1(String field1) {
this.field1 = field1;
}
public int getField2() {
return field2;
}
public void setField2(int field2) {
this.field2 = field2;
}
}
问题1:性能问题
问题2:循环引用
IdentityHashMap
记录已经访问过的对象,避免重复复制。问题3:私有字段访问
field.setAccessible(true)
)。通过以上方法,可以实现一个基本的深度复制工具,但在实际应用中可能需要根据具体情况进行调整和优化。
领取专属 10元无门槛券
手把手带您无忧上云