![](/img/trans.png)
[英]Why does Java's Collection<E>.toArray() return an Object[] rather than an E[]?
[英]Why does Java's TreeSet<E> remove(Object) not take an E
從Java 6 TreeSet<E>
文檔:
boolean remove(Object o):
Removes the specified element from this set if it is present.
為什么這會接受Object而不是泛型E? 唯一可以添加的對象是E類型,因此唯一的可移動類型應該是E類型。
從第一條評論中回答:
神話:
一個流行的神話是它是愚蠢和邪惡的,但由於向后兼容性,它是必要的。 但兼容性論點無關緊要; 無論您是否考慮兼容性,API都是正確的。
真正的原因:
統一地,Java Collections Framework(以及Google Collections Library)的方法從不限制其參數的類型,除非必須防止集合被破壞。
在這里閱讀更多: 為什么Set.contains()采用對象而不是E?
remove()
,就像get()
在給定一個相等的元素(就.equals()
)時一樣。 在Java中,不同類的對象可能(在某些情況下是必需的)是相同的。 因此,您不應該限制類型。
好吧,每個E也是一個對象,也許你現在有E不是E(例如來自一個事件源),這對你來說很方便。 否則你只需要將其強制轉換為E即可將其刪除。
從平等的角度來看,這無關緊要:如果給定對象的引用地址等於集合的內容,則對其進行測試,因此它與哪個類無關。
這確實是個問題。 如果有人調用remove(o)
而o
的類型不是E
,那么通常是編程錯誤試圖刪除錯誤的東西。 類型檢查無法保護我們免受錯誤的影響。
雖然一個好的IDE(IntelliJ)可以檢測到這些問題並警告我們,但API設計者應該提供更精確的簽名來利用編譯器類型檢查。 (IDE在這里作弊 - 它知道Set.remove()
的含義,因為它是一個標准Set.remove()
不會為自定義API提供相同的幫助)
對於像contains()
這樣的查詢API,可以接受非E
參數並返回一個簡單的false。 所以我們可以同時擁有
boolean contains(Object o);
boolean contains2(E o);
對於像remove()
這樣的變異API,它是否應該接受非E
參數是有爭議的。 然而,鑒於擦除的現實,辯論將沒有實際意義 - 除了接受非E論證並對此保持沉默之外別無選擇。 我們仍然可以有兩種方法
boolean remove(Object o);
boolean remove2(E o);
在大多數情況下,程序員可以調用contains2/remove2
以獲得額外的類型安全性。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.