Java 深度克隆
工具类
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
public class BeanUtil
{
/**
* 基本数据类型的引用类型
*/
private static List<Class<?>> baseType = new ArrayList<Class<?>>();
/*
* 单一的数据类型
*/
private static List<Class<?>> simpleType = new ArrayList<Class<?>>();
static
{
baseType.add(Byte.class);
baseType.add(Short.class);
baseType.add(Integer.class);
baseType.add(Long.class);
baseType.add(Float.class);
baseType.add(Double.class);
baseType.add(Character.class);
baseType.add(Boolean.class);
simpleType.addAll(baseType);
simpleType.add(String.class);
simpleType.add(Date.class);
simpleType.add(java.sql.Date.class);
}
@SuppressWarnings("unchecked")
public static <T> T deepClone(T pojo) throws Exception
{
if(pojo == null)
return null;
Class<?> pojoClass = pojo.getClass();
if(simpleType.contains(pojoClass) || pojoClass.getName().startsWith("[") || List.class.isAssignableFrom(pojoClass) || Map.class.isAssignableFrom(pojoClass))
{
return (T) copyValue(pojoClass, pojo);
}
Constructor<T> constructor = (Constructor<T>) pojoClass.getDeclaredConstructor();
T bean = constructor.newInstance();
Field[] fields = pojo.getClass().getDeclaredFields();
for(Field field : fields)
{
copyFieldValue(pojo, bean, field);
}
return bean;
}
@SuppressWarnings("unchecked")
public static <T> T copyValue(Class<T> clazz, Object oldPojo) throws Exception
{
if(oldPojo == null)
return null;
if(clazz.isPrimitive())
{//基本数据类型
return (T) oldPojo;
}
if(baseType.contains(clazz))
{//基本数据类型的引用类型
Method method = clazz.getMethod("valueOf", (Class<?>) clazz.getField("TYPE").get(null));
return (T) method.invoke(null, oldPojo);
}
if(clazz == String.class)
{
return (T) new String((String) oldPojo);
}
if(clazz == Date.class)
{
Date date = (Date) oldPojo;
return (T) new Date(date.getTime());
}
if(clazz == java.sql.Date.class)
{
java.sql.Date date = (java.sql.Date) oldPojo;
return (T) new java.sql.Date(date.getTime());
}
String clazzName = clazz.getName();
if(clazzName.startsWith("["))
{//数组
Object oldArray = oldPojo;
int oldLen = Array.getLength(oldArray);
Object firstObj = Array.get(oldArray, 0);
Class<?> itemClazz = firstObj.getClass();
if(baseType.contains(itemClazz))
{//针对基础类型自动装箱成增强类型
if(clazzName.charAt(1) != '[' && clazzName.charAt(1) != 'L')
{
itemClazz = (Class<?>) itemClazz.getField("TYPE").get(null);
}
}
Object newArray = Array.newInstance(itemClazz, oldLen);
for(int i = 0; i < oldLen; i++)
{
Object item = Array.get(oldArray, i);
Array.set(newArray, i, BeanUtil.deepClone(item));
}
return (T) newArray;
}
if(List.class.isAssignableFrom(clazz))
{//List集合
List<?> oldList = (List<?>) oldPojo;
List<Object> newList = oldList.getClass().getDeclaredConstructor(Integer.TYPE).newInstance(oldList.size());
for(Object obj : oldList)
{
newList.add(BeanUtil.deepClone(obj));
}
return (T) newList;
}
if(Map.class.isAssignableFrom(clazz))
{
Map<?, ?> oldMap = (Map<?, ?>) oldPojo;
Map<Object, Object> newMap = oldMap.getClass().getDeclaredConstructor(Integer.TYPE).newInstance(oldMap.size());
for(Object key : oldMap.keySet())
{
Object value = oldMap.get(key);
newMap.put(BeanUtil.deepClone(key), BeanUtil.deepClone(value));
}
return (T) newMap;
}
return BeanUtil.deepClone((T) oldPojo);
}
public static <T> void copyFieldValue(T oldPojo, T newPojo, Field field) throws Exception
{
if("serialVersionUID".equals(field.getName()))
{
return;
}
Class<?> clazz = field.getType();
//强制对此字段进行赋值操作
//http://blog.csdn.net/yaerfeng/article/details/7103397
field.setAccessible(true);
if(clazz.isPrimitive())
{//基本数据类型
field.set(newPojo, field.get(oldPojo));
return;
}
Object oldValue = field.get(oldPojo);
if(oldValue == null)
{
return;
}
field.set(newPojo, copyValue(clazz, oldValue));
}
}
测试Pojo
BasePojo
public class BasePojo
{
private String id;
//getter、setter省略
}
TestClass
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
public class TestClass
{
private String name;
private int age;
private boolean flag;
private Double money;
private Date borthDay;
private BasePojo basePojo;
private int[] intArr;
private Double[] doubleArr;
private List<BasePojo> basePojos;
private Map<String, BasePojo> basePojoMap;
//getter、setter省略
}
测试类
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Test;
public class BeanUtilTest
{
@Test
public void test() throws Exception
{
int[] intArr = { 1, 2 };
Double[] doubleArr = new Double[] { 5.5, 6.6 };
BasePojo basePojo1 = new BasePojo();
BasePojo basePojo2 = new BasePojo();
BasePojo basePojo3 = new BasePojo();
BasePojo basePojo4 = new BasePojo();
BasePojo basePojo5 = new BasePojo();
basePojo1.setId("1");
basePojo2.setId("2");
basePojo3.setId("3");
basePojo4.setId("4");
basePojo5.setId("5");
List<BasePojo> basePojos = new ArrayList<BasePojo>();
basePojos.add(basePojo2);
basePojos.add(basePojo3);
Map<String, BasePojo> basePojoMap = new HashMap<String, BasePojo>();
basePojoMap.put(basePojo4.getId(), basePojo4);
basePojoMap.put(basePojo5.getId(), basePojo5);
TestClass tc1 = new TestClass();
System.out.println(tc1);
tc1.setAge(24);
tc1.setMoney(5.5);
tc1.setName("xych");
tc1.setFlag(true);
tc1.setIntArr(intArr);
tc1.setDoubleArr(doubleArr);
tc1.setBasePojo(basePojo1);
tc1.setBasePojos(basePojos);
tc1.setBasePojoMap(basePojoMap);
System.out.println(tc1);
TestClass tc2 = BeanUtil.deepClone(tc1);
System.out.println(tc1);
System.out.println(tc2);
}
@Test
public void test1() throws Exception
{
int b = BeanUtil.deepClone(5);
System.out.println(b);
Character aa = 'y';
Character bb = BeanUtil.deepClone(aa);
System.out.println(aa + " " + bb + " " + (aa == bb));
Integer aaa = 129;
Integer bbb = BeanUtil.deepClone(aaa);
System.out.println(aaa + " " + bbb + " " + (aaa == bbb));
}
@Test
public void test2() throws Exception
{
int[] arr = new int[] { 1, 2 };
int[] arr2 = BeanUtil.deepClone(arr);
System.out.println(arr);
System.out.println(arr2);
arr2[1] = 3;
System.out.println(arr[1]);
System.out.println(arr2[1]);
//
String[] strArr1 = new String[] { "1", "2" };
String[] strArr2 = BeanUtil.deepClone(strArr1);
strArr2[1] = "3";
System.out.println(strArr1 + " " + strArr1[1]);
System.out.println(strArr2 + " " + strArr2[1]);
System.out.println(strArr1[0] == strArr2[0]);
//
BasePojo[] bpArr1 = new BasePojo[2];
BasePojo bp1 = new BasePojo();
bp1.setId("1");
BasePojo bp2 = new BasePojo();
bp2.setId("2");
bpArr1[0] = bp1;
bpArr1[1] = bp2;
BasePojo[] bpArr2 = BeanUtil.deepClone(bpArr1);
bpArr2[1].setId("5");
System.out.println(bpArr1[1].getId());
System.out.println(bpArr2[1].getId());
}
@Test
public void test3() throws Exception
{
List<String> strList1 = new ArrayList<String>();
strList1.add("1");
strList1.add("2");
List<String> strList2 = BeanUtil.deepClone(strList1);
System.out.println(strList1);
System.out.println(strList2);
System.out.println(strList1.get(1) == strList2.get(1));
//
List<BasePojo> bpList1 = new ArrayList<BasePojo>();
BasePojo bp1 = new BasePojo();
bp1.setId("1");
BasePojo bp2 = new BasePojo();
bp2.setId("2");
bpList1.add(bp1);
bpList1.add(bp2);
List<BasePojo> bpList2 = BeanUtil.deepClone(bpList1);
System.out.println(bpList1);
System.out.println(bpList2);
}
@Test
public void test4() throws Exception
{
Map<String, String> map = new HashMap<String, String>();
map.put("1", "2");
map.put("3", "4");
Map<String, String> map2 = BeanUtil.deepClone(map);
map2.put("3", "6");
System.out.println(map);
System.out.println(map2);
}
public static void main(String[] args) throws Exception
{
new BeanUtilTest().test();
}
}
测试结果
test()测试结果
test1()测试结果
5
y y true
129 129 false
test2()测试结果
[I@3cb89838
[I@7b11a3ac
2
3
[Ljava.lang.String;@4310b053 2
[Ljava.lang.String;@7ca83b8a 3
false
2
5
test3()测试结果
test4()测试结果
{3=4, 1=2}
{3=6, 1=2}
源代码:https://github.com/Lanboo/com.xych
见 com.xych.framework.api.common.util