關於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\)就不是同一個東西了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章