Java 深度克隆

来源:互联网 发布:淘宝买单机游戏 编辑:程序博客网 时间:2024/06/06 13:06

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()测试结果

test()方法测试结果

test1()测试结果

5y y true129 129 false

test2()测试结果

[I@3cb89838[I@7b11a3ac23[Ljava.lang.String;@4310b053 2[Ljava.lang.String;@7ca83b8a 3false25

test3()测试结果

test3()方法测试结果

test4()测试结果

{3=4, 1=2}{3=6, 1=2}

源代码:https://github.com/Lanboo/com.xych
见 com.xych.framework.api.common.util