引用对象深度复制的简单实现方法
注:此种方式受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);