Fastjson JSONObject/JSONArray new Type(Object)深复制失败的原因
目录
Fastjson JSONObject/JSONArray new Type(Object)深复制失败的原因
由fastjson 的 JSONObject深复制 和 JSONArray深复制 各自第一个例子中使用new JSONObject(Object) 和 new JSONArray(Object)进行深复制失败了,其中的原因呢?
1,new JSONObject (Object);
代码:
public static void main(String[] args){
testNewJson();
}
public static void testNewJson(){
System.out.println("====== new JSONObject fail =======");
JSONObject one = new JSONObject();
one.put("one","fish");
JSONObject two = new JSONObject(one);
System.out.println("init: one: "+ one.toString());
System.out.println("init: two: "+ two.toString());
two.put("one","grass");
System.out.println("change: one: "+ one.toString());
System.out.println("change: two: "+ two.toString());
System.out.println("内存地址: one: "+ System.identityHashCode(one));
System.out.println("内存地址: two: "+ System.identityHashCode(two));
System.out.println();
}
结果:
====== new JSONObject fail =======
init: one: {"one":"fish"}
init: two: {"one":"fish"}
change: one: {"one":"grass"}
change: two: {"one":"grass"}
内存地址: one: 544724190
内存地址: two: 1972439101
new JSONObject(one) 这种方式失败了。
内容地址也不同,应该会一样才对,然而并没有?为什么呢?
看源码:
private final Map<String, Object> map;
public JSONObject(Map<String, Object> map) {
if (map == null) {
throw new IllegalArgumentException("map is null.");
} else {
this.map = map;
}
}
public Object put(String key, Object value) {
return this.map.put(key, value);
}
调试:
JSONObject one = new JSONObject();
one.put("one","fish");
JSONObject two = new JSONObject(one);
two.put("one","grass");
两个内容还是指向同一个map内容,变成了复制引用,two赋值的时候,也会改变one的内容。
2,new JSONArray(Object);
代码:
public static void main(String[] args){
testNewJsonArr();
}
public static void testNewJsonArr(){
System.out.println("====== new JSONArray fail =======");
JSONArray oneArr = new JSONArray();
JSONObject one = new JSONObject();
one.put("one","fish");
oneArr.add(one);
JSONArray twoArr = new JSONArray(oneArr);
System.out.println("init: oneArr: "+ oneArr.toString());
System.out.println("init: twoArr: "+ twoArr.toString());
System.out.println("====== add bird =======");
JSONObject two = new JSONObject();
two.put("two","bird");
twoArr.add(two);
System.out.println("change: oneArr: "+ oneArr.toString());
System.out.println("change: twoArr: "+ twoArr.toString());
System.out.println("内存地址: oneArr: "+ System.identityHashCode(oneArr));
System.out.println("内存地址: twoArr: "+ System.identityHashCode(twoArr));
System.out.println("====== fail =======");
}
结果:
====== new JSONArray fail =======
init: oneArr: [{"one":"fish"}]
init: twoArr: [{"one":"fish"}]
====== add bird =======
change: oneArr: [{"one":"fish"},{"two":"bird"}]
change: twoArr: [{"one":"fish"},{"two":"bird"}]
内存地址: oneArr: 544724190
内存地址: twoArr: 277630005
====== fail =======
New JSONArray的方式失败,为什么失败呢?
看内存的地址是不同的,但结果还是变成了复制引用。
源码:
private final List<Object> list;
public JSONArray(List<Object> list) {
if (list == null) {
throw new IllegalArgumentException("list is null.");
} else {
this.list = list;
}
}
public boolean add(Object e) {
return this.list.add(e);
}
调试:
oneArr.add(one);
twoArr.add(two);
调式的时候,发现两个内容还是指向同一个list内容,变成了复制引用,twoArr添加内容的时候,也会改变oneArr的内容。
3,处理:
了解了fastjson里面的JSONObject和JSONArray,不能使用new JSONObject(Object),new JSONArray(Object)进行深度复制的原因。那有办法进行改写处理吗? 由上面的源码可以看到
private final Map<String, Object> map;
private final List<Object> list;
属性里面都加了final字段,由final关键字的特性:“如果引用为引用数据类型,比如对象、数组,则该对象、数组本身可以修改,但指向该对象或数组的地址的引用不能修改”,目前看似乎是无解的,只能另寻他路,比如使用putAll或是addAll的方式进行处理了。
总结:
在使用fastjon 的JSONObject和JSONArray进行深度复制的时候,我以为可以跟map和list的方式一样的,然而却不相同,调试源码的时候,才发现原因。对于有些现象,自己搞不懂的,要耐下心来,好好去看下源码,调式下,也许会发现问题。再不行就问问大佬。学习嘛,常说要有“打破砂锅问到底”的精神。