任意JAVA对象的深度拷贝

本文介绍了一个用于Java对象深度复制的工具类,支持多种复杂类型的复制,并提供了浅拷贝和深拷贝的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

有时候需要深度复制任意的JAVA对象(无论是否实现Cloneable接口或序列化接口),但发现BeanUtils不太好用,因此写了以下工具类来进行深度复制。

package com.n_app.util;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
* 克隆工具类
* @author lujijiang@gmail.com
*
*/
public class Clone {
/**
* 无需进行复制的特殊类型数组
*/
static Class[] needlessCloneClasses = new Class[]{String.class,Boolean.class,Character.class,Byte.class,Short.class,
Integer.class,Long.class,Float.class,Double.class,Void.class,Object.class,Class.class
};
/**
* 判断该类型对象是否无需复制
* @param c 指定类型
* @return 如果不需要复制则返回真,否则返回假
*/
private static boolean isNeedlessClone(Class c){
if(c.isPrimitive()){//基本类型
return true;
}
for(Class tmp:needlessCloneClasses){//是否在无需复制类型数组里
if(c.equals(tmp)){
return true;
}
}
return false;
}

/**
* 尝试创建新对象
* @param c 原始对象
* @return 新的对象
* @throws IllegalAccessException
*/
private static Object createObject(Object value) throws IllegalAccessException{
try {
return value.getClass().newInstance();
} catch (InstantiationException e) {
return null;
} catch (IllegalAccessException e) {
throw e;
}
}

/**
* 复制对象数据
* @param value 原始对象
* @param level 复制深度。小于0为无限深度,即将深入到最基本类型和Object类级别的数据复制;
* 大于0则按照其值复制到指定深度的数据,等于0则直接返回对象本身而不进行任何复制行为。
* @return 返回复制后的对象
* @throws IllegalAccessException
* @throws InstantiationException
* @throws InvocationTargetException
* @throws NoSuchMethodException
*/
public static Object clone(Object value,int level) throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException{
if(value==null){
return null;
}
if(level==0){
return value;
}
Class c = value.getClass();
if(isNeedlessClone(c)){
return value;
}
level--;
if(value instanceof Collection){//复制新的集合
Collection tmp = (Collection)c.newInstance();
for(Object v:(Collection)value){
tmp.add(clone(v,level));//深度复制
}
value = tmp;
}
else if(c.isArray()){//复制新的Array
//首先判断是否为基本数据类型
if(c.equals(int[].class)){
int[] old = (int[])value;
value = (int[])Arrays.copyOf(old, old.length);
}
else if(c.equals(short[].class)){
short[] old = (short[])value;
value = (short[])Arrays.copyOf(old, old.length);
}
else if(c.equals(char[].class)){
char[] old = (char[])value;
value = (char[])Arrays.copyOf(old, old.length);
}
else if(c.equals(float[].class)){
float[] old = (float[])value;
value = (float[])Arrays.copyOf(old, old.length);
}
else if(c.equals(double[].class)){
double[] old = (double[])value;
value = (double[])Arrays.copyOf(old, old.length);
}
else if(c.equals(long[].class)){
long[] old = (long[])value;
value = (long[])Arrays.copyOf(old, old.length);
}
else if(c.equals(boolean[].class)){
boolean[] old = (boolean[])value;
value = (boolean[])Arrays.copyOf(old, old.length);
}
else if(c.equals(byte[].class)){
byte[] old = (byte[])value;
value = (byte[])Arrays.copyOf(old, old.length);
}
else {
Object[] old = (Object[])value;
Object[] tmp = (Object[])Arrays.copyOf(old, old.length, old.getClass());
for(int i = 0;i<old.length;i++){
tmp[i] = clone(old[i],level);
}
value = tmp;
}
}
else if(value instanceof Map){//复制新的MAP
Map tmp = (Map)c.newInstance();
Map org = (Map)value;
for(Object key:org.keySet()){
tmp.put(key, clone(org.get(key),level));//深度复制
}
value = tmp;
}
else {
Object tmp = createObject(value);
if(tmp==null){//无法创建新实例则返回对象本身,没有克隆
return value;
}
Set<Field> fields = new HashSet<Field>();
while(c!=null&&!c.equals(Object.class)){
fields.addAll(Arrays.asList(c.getDeclaredFields()));
c = c.getSuperclass();
}
for(Field field:fields){
if(!Modifier.isFinal(field.getModifiers())){//仅复制非final字段
field.setAccessible(true);
field.set(tmp, clone(field.get(value),level));//深度复制
}
}
value = tmp;
}
return value;
}

/**
* 浅表复制对象
* @param value 原始对象
* @return 复制后的对象,只复制一层
* @throws IllegalAccessException
* @throws InstantiationException
* @throws InvocationTargetException
* @throws NoSuchMethodException
*/
public static Object clone(Object value) throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException{
return clone(value,1);
}

/**
* 深度复制对象
* @param value 原始对象
* @return 复制后的对象
* @throws IllegalAccessException
* @throws InstantiationException
* @throws InvocationTargetException
* @throws NoSuchMethodException
*/
public static Object deepClone(Object value) throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException{
return clone(value,-1);
}
}


注:此复制方法是非安全的,对于某些特殊情况将无法复制其值,比如final字段和无空构造方法的类型等,仅适用于复制普通DTO、POJO等,其它场合请慎用。
Java中,集合的拷贝构造函数通常只提供浅拷贝,而不是深拷贝。这意味着原始集合和克隆集合中存储的对象是相同的,指向Java堆内存中相同的位置。如果修改了原始集合中的对象信息,克隆集合也会受到影响,反之亦然。所以,如果需要进行集合的深拷贝,需要采用其他方法。 一个可行的深拷贝集合的方法是使用递归来克隆集合中的对象,直到基本数据类型或者不可变类。这个过程可以通过创建一个新的集合对象,并将原始集合中的每个元素逐个克隆并添加到新的集合中。这样就可以确保克隆集合与原始集合完全独立。然后就可以对克隆集合进行任意的修改,而不会对原始集合产生任何影响。 在给定的引用中,展示了一个使用递归方法来进行深拷贝的示例代码。该示例代码是一个求取整数数组的所有子集的方法,其中使用了递归来生成子集。递归的过程中,通过创建新的集合对象,并将原始集合中的元素逐个添加到新的集合中,实现了深拷贝的效果。 因此,要进行Java集合的深拷贝,可以使用递归方法来克隆集合中的对象,确保克隆集合与原始集合完全独立。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [java中list集合的深度拷贝](https://blog.youkuaiyun.com/u010398493/article/details/52840076)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值