引用对象深度复制的简单实现方法

注:此种方式受fastjson底层影响,在含有long、double等类型的对象复制后再次反序列化时会出现格式转换错误,推荐使用:https://www.cnblogs.com/nvsky/p/13995574.html

 

我们有时候会遇到某个List集合循环几次并修改其属性或赋值给其他集合等操作,但当程序运行完会发现,运行的结果并不如预期,有可能第二次循环的时候原List内的数据已经发生了变化,但我们没有直接的去修改原List的内容,比如下面的例子:

List<DataObject> dataList = new ArrayList<>();
dataObject1.setId(13);
dataList.add(dataObject1);
List<DataObject> newDataList = new ArrayList<>();
newDataList.add(dataList.get(0));
DataObject dataObject2 = newDataList.get(0);
dataObject2.setId(15);

我们并没有直接修改dataList的数据,而是赋值给新的对象后再操作的新的对象,但执行后发现,dataList的数据也会跟着改变,因为dataObject1是个应用类型对象,它的地址并没有因为赋值到新的集合内而改变,即使你new一个DataObject,然后 = dataObject1或者调用clone方法,地址依然没有改变,这是因为引用类型的对象在复制时只是浅度复制,并没有重新生成一个对象,而基本类型则不会有这个问题。

那怎么解决这个问题呢?网上有许多方法,比如Cloneable、序列化等等,写起来比较麻烦,并且有时还需要trycatch,这个有一个简单的方法来实现对象的深度复制,那就是利用JSONObject的转换实现,其实也是通过序列化的方式,但不用亲自动手去序列化反序列化:

JSONObject.parseArray(JSONObject.toJSONString(dataList)).toJavaList(DataObject.Class)

先将dataList转成jsonString,即序列化,然后再转成jsonArray并转成java对象,即反序列化

转换前:

 

 转换后:

 

 最后提供一下使用这个封装的工具类,两个方法,一个复制单对象,一个复制List集合:

    /**
     * @author: shenzhikui
     * @description: 利用json转换实现变相深度复制
     * @date: 2019/11/7
     * @param data
     * @param tClass
     * @return
     */
    public static <T> T deepCopy(T data, Class<T> tClass){
        T bakData = JSONObject.parseObject(JSONObject.toJSONString(data)).toJavaObject(tClass);
        return bakData;
    }

    /**
     * @author: shenzhikui
     * @description: 利用json转换实现变相深度复制 list
     * @date: 2019/11/7
     * @param dataList
     * @param tClass
     * @return 
     */
    public static <T> List<T> deepCopy(List<T> dataList, Class<T> tClass){
        List<T> bakList = new ArrayList<>();
        if(null != dataList && dataList.size() > 0){
            bakList.addAll(JSONObject.parseArray(JSONObject.toJSONString(dataList)).toJavaList(tClass));
        }
        return bakList;
    }

 使用方法:

List<DataObject> newDataList = deepCopy(dataList,DataObject.class);

 

posted @ 2019-11-08 14:55  某天清晨、  阅读(487)  评论(0编辑  收藏  举报