java核心技術卷I-視圖

視圖與包裝器

通過使用視圖( views) 可以獲得其他的實現了 Collection 接口和 Map 接口的對象。映射類的 keySet 方法就是一個這樣的示例。初看起來, 好像這個方法創建了一個新集, 並將映射中的所有鍵都填進去,然後返回這個集。但是, 情況並非如此。取而代之的是:keySet 方法返回一個實現 Set接口的類對象, 這個類的方法對原映射進行操作。這種集合稱爲視圖。

輕量級集合包裝器

Arrays 類的靜態方法 asList 將返回一個包裝了普通 Java 數組的 List 包裝器。這個方法可以將數組傳遞給一個期望得到列表或集合參數的方法。

Card[] cardOeck = new Card [52];
List<Card> cardList = Arrays.asList(cardDeck):

返回的對象不是 ArrayList。它是一個視圖對象, 帶有訪問底層數組的 get 和 set 方法。改變數組大小的所有方法(例如,與迭代器相關的 add 和 remove 方法)都會拋出一個Unsupported OperationException 異常。
這個方法調用

Collections.nCopies(n, anObject)

將返回一個實現了 List 接口的不可修改的對象, 並給人一種包含n個元素, 每個元素都像是一個 anObject 的錯覺。
Collections 類包含很多實用方法, 這些方法的參數和返回值都是集合。 不要將它與 Collection 接口混淆起來。

子範圍

可以爲很多集合建立子範圍(subrange ) 視圖。例如, 假設有一個列表 staff, 想從中取出第10 個 ~ 第19個元素。可以使用 subList 方法來獲得一個列表的子範圍視圖。

List group2 = staff.subList(10, 20);

第一個索引包含在內, 第二個索引則不包含在內。

不可修改的視圖

Collections 還有幾個方法, 用於產生集合的不可修改視圖 ( unmodifiable views)。這些視圖對現有集合增加了一個運行時的檢查。如果發現試圖對集合進行修改, 就拋出一個異常,同時這個集合將保持未修改的狀態。
在這裏插入圖片描述
假設想要查看某部分代碼, 但又不觸及某個集合的內容

List<String> staff = new LinkedList<>();
lookAt(Collections.unmodifiableList(staff));

Collections-unmodifiableList 方法將返回一個實現 List 接口的類對象。 其訪問器方法將從staff 集合中獲取值。當然,lookAt 方法可以調用 List 接口中的所有方法,而不只是訪問器。但是所有的更改器方法(例如, add) 已經被重新定義爲拋出一個UnsupportedOperationException異常,而不是將調用傳遞給底層集合。
由於視圖只是包裝了接口而不是實際的集合對象, 所以只能訪問接口中定義的方法。例如, LinkedList 類有一些非常方便的方法,addFirst 和 addLast,它們都不是 List 接口的方法,不能通過不可修改視圖進行訪問。

同步視圖

如果由多個線程訪問集合,就必須確保集不會被意外地破壞。例如, 如果一個線程試圖將元素添加到散列表中,同時另一個線程正在對散列表進行再散列,其結果將是災難性的。
類庫的設計者使用視圖機制來確保常規集合的線程安全,而不是實現線程安全的集合類。例如, Collections 類的靜態 synchronizedMap方法可以將任何一個映射錶轉換成具有同步訪問方法的 Map:

Map<String, Employee> map = Collections.synchronizedMap(new HashMap<String, Employee>();

現在,就可以由多線程訪問 map 對象了。像 get 和 put 這類方法都是同步操作的,即在另一個線程調用另一個方法之前,剛纔的方法調用必須徹底完成。

受查視圖

“ 受査” 視圖用來對泛型類型發生問題時提供調試支持。如同第 8 章中所述, 實際上將錯誤類型的元素混人泛型集合中的問題極有可能發生。

ArrayList<String> strings = new ArrayList<>();
ArrayList rawList = strings; // warning only, not an error, for compatibility with legacy code
rawList.add(new Date()); // now strings contains a Date object!

受査視圖可以探測到這類問題。下面定義了一個安全列表

List<String> safestrings = Collections.checkedList(strings,String,class);

視圖的 add 方法將檢測插人的對象是否屬於給定的類。如果不屬於給定的類,就立即拋出一個 ClassCastException。這樣做的好處是錯誤可以在正確的位置得以報告:

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