關於List中的大大坑(二)

List的前兩個坑:https://blog.csdn.net/Lucky_Boy_Luck/article/details/105715419
接下來是第三個坑:

1.3 不可變集合

        爲了防止 List 集合被誤操作,我們可以使用 Collections.unmodifiableList() 生成一個不可變(immutable)集合,進行防禦性編程。

        這個不可變集合只能被讀取,不能做任何修改,包括增加,刪除,修改,從而保護不可變集合的安全。

舉個小例子:

public class Test {

    public static void main(String[] args) {
        List<String> list = new ArrayList<>(Arrays.asList("dog", "cat"));
        List<String> unmodifiableList = Collections.unmodifiableList(list);

        unmodifiableList.add("pig");
        System.out.println(list);
        System.out.println(unmodifiableList);
    }
}

在這裏插入圖片描述
        運行結果表明:程序運行在add()方法時,會拋出UnsupportedOperationException異常。這說明,確實生成了不可變集合。

查看源碼:
首先調用Collections.unmodifiableList()方法:
在這裏插入圖片描述
而UnmodifiableList是CollectionUtils類中的一個內部類,且實現了接口List。
在這裏插入圖片描述
查看其中部分方法:
在這裏插入圖片描述
發現set()/add()/remove()方法等都拋出UnsupportedOperationException異常。

所以:

unmodifiableList.add("pig");

程序運行到上面那條語句就會拋出UnsupportedOperationException異常

有趣事例

        如果你不小心改動原始 List,你就會發現這個不可變集合,竟然就變了。。。

        如,對上面個例子進行修改。修改原集合下標爲0的元素,把“dog”修改爲“goat”

public class Test {

    public static void main(String[] args) {
        List<String> list = new ArrayList<>(Arrays.asList("dog", "cat"));
        List<String> unmodifiableList = Collections.unmodifiableList(list);

        list.set(0, "goat");
        System.out.println(list.get(0));
        System.out.println(unmodifiableList.get(0));
    }
}

在這裏插入圖片描述
運行結果:發現不可變集合的第一個元素竟然也變了。

查看源碼:
首先調用Collections.unmodifiableList()方法:
在這裏插入圖片描述
會調用Collections類中的內部類UnmodifiableList構造方法
在這裏插入圖片描述
        在構造方法中,對其成員變量list賦值時,並沒有新new 一個List,而是使用了原來的list。這其實跟之前的ArrayList類中的內部類 SubList 是同一個問題-------新集合底層實際使用了原始 List。

所以,對原集合的修改,會改變不可變集合的內容

        由於不可變集合所有修改操作都會報錯,所以不可變集合不會產生任何改動,所以並不影響的原始集合。但是反過來,卻不行,原始 List 隨時都有可能被改動,從而影響不可變集合。

1.4 foreach 增加/刪除元素大坑

這部分有在這篇文章中涉及到:Java中的fail-fast機制

轉載

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