关于JAVA的引用(地址)的一些理解

之前遇到一些关于两个引用类型是否指向同一个对象的问题,如下定义的\(ResponseObject\)中的,在这个类中,先将 \(data\) 从 \(jsonObject\) 中取出,随后所有的操作都从 \(data\) 中进行操作。
之前一直以为 \(jsonObject\) 中的 \(data\) 无论如何都是会跟着外面的 \(data\) 一起发生变化的,实际上并不一定。

class ResponseObject {
    public JSONObject data;
    private JSONObject jsonObject;
    ResponseObject(JSONObject jsonObject) {
        this.data = jsonObject.getJSONObject("data");
        this.jsonObject = jsonObject;
    }

    public void put(String key, Object value) {
        if (data == null) {
            data = new JSONObject();
            this.jsonObject.put("data", data);
        }
        data.put(key, value);
    }
    public JSONObject getData() {
        return this.jsonObject.getJSONObject("data");
    }
}

按道理来说, \(jsonObject\) 中的 \(data\) 和外面的 \(data\) 指向的是同一个对象,也就是说他们的地址是相同的。
进行测试

public class Test {
    public static void main(String[] args) {
        JSONObject jsonObject = new JSONObject();
        JSONObject data = new JSONObject();
        jsonObject.put("data", data);

        ResponseObject t = new ResponseObject(jsonObject);

        JSONObject bearObj = new JSONObject();
        t.put("bear",  bearObj);

        System.out.println(System.identityHashCode(t.getData()));
        System.out.println(System.identityHashCode(t.data)); //不能仅用hashCode()来判断,若复写了hashCode()则输出的就不是地址。

    }
}

上面的输出为:

{"bear":{}}
{"bear":{}}
83954662
83954662

确实和期望一样,插入元素之后两者都发生了变化,且地址也是一样的,可见他们是指向相同的对象的。
但我们做以下的更改:

public class Test {
    public static void main(String[] args) {
        JSONObject jsonObject = new JSONObject();
        Map<String, Object> data = new HashMap<String, Object>();
        jsonObject.put("data", data);

        ResponseObject t = new ResponseObject(jsonObject);

        JSONObject bearObj = new JSONObject();
        t.put("bear",  bearObj);

        System.out.println(t.getData());
        System.out.println(t.data);
        System.out.println(System.identityHashCode(t.getData()));
        System.out.println(System.identityHashCode(t.data));

    }
}

发现输出和期望的就有所不同了:

{}
{"bear":{}}
777874839
1751075886

原因很简单,通过观察 \(com.alibaba.fastjson.JSONObject\) 的代码

public JSONObject getJSONObject(String key) {
        Object value = map.get(key);

        if (value instanceof JSONObject) {
            return (JSONObject) value;
        }

        if (value instanceof String) {
            return JSON.parseObject((String) value);
        }

        return (JSONObject) toJSON(value);
    }

发现这个方法在 \(data\) 不是 \(JSONObject\) 类时,会新建一个 \(JSONObject\) 然后再将元素插入进去,因此地址会发生改变,这种时候\(ResponseObject\)中的\(data\)与\(jsonObject\)中的\(data\)就不是同一个东西了。

上一篇:Java工具:Java递归去除Json字符串空值(key和value)


下一篇:Java对象转jsonobject被截断,分享一点面试小经验