簡體   English   中英

為什么Java的TreeSet <E> remove(Object)不帶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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM