Java 深度克隆

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

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

test3()方法测试结果

test4()测试结果

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

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值