它是否與舊版(非通用版)Collection
保持向後兼容?還是有一個更微妙的細節,我失蹤了?我在remove
也看到這種模式(remove(Object o)
),但add
被通用化爲add(E e)
。爲什麼我們要包含(Object o)而不是Containers(E e)?
回答
需要Object
,因爲它匹配的對象不必與您傳入的對象類型相同;它只需要它們是平等的。從,contains(o)
的規範中返回true,如果有對象e
使得(o==null ? e==null : o.equals(e))
爲真。請注意,沒有任何要求o
和e
是同一類型。這是因爲equals()
方法採用Object
作爲參數,而不僅僅是與對象相同的類型。
雖然很多類定義了equals()
,這樣它的對象只能等於它自己類的對象,但通常情況並非總是如此。例如,List.equals()
的規範說,如果兩個List
對象都是List
s,並且具有相同內容,即使它們是List的不同實現,它們也是相等的。所以回到這個問題的例子中,有可能有一個Collection<ArrayList>
,我可以用LinkedList
作爲參數調用,如果列表中有相同的內容,它可能會返回true。如果是通用的並且將其參數類型限制爲E
,則這將不可能。
事實上,接受任何對象作爲參數的事實允許一個有趣的使用,你可以用它來測試集合中的一個對象,滿足某些屬性的存在:
Collection<Integer> integers;
boolean oddNumberExists = integers.contains(new Object() {
public boolean equals(Object e) {
Integer i = (Integer)e;
if (i % 2 != 0) return true;
else return false;
}
});
此方法簽名'包含(對象o)'提供了一個非常好的槍,可以方便地拍攝自己的腳。這種方法實際上是Java泛型限制的展示。 – 2010-06-08 13:21:40
這是因爲contains
功能利用equals
功能和equals
功能是在基對象類中定義與equals(Object o)
而非equals(E e)
簽名(因爲不是所有的類是通用的)。與remove
函數的情況相同 - 它使用帶有Object參數的equals
函數遍歷集合。
但是,這並不直接解釋這個決定,因爲他們可能仍然使用E類型,並允許它在equals
的調用中被自動強制類型爲Object;但我想他們希望允許在其他對象類型上調用該函數。有一個Collection<Foo> c;
,然後調用c.contains(somethingOfTypeBar)
沒什麼錯 - 它總是會返回false,所以它不需要強制類型輸入Foo(可以拋出異常),或者爲了防止異常,調用typeof
。所以你可以想象,如果你正在迭代混合類型的東西,並且在每個元素上調用contains
,那麼你可以簡單地在所有元素上使用contains函數,而不是需要守衛。
它實際上是讓人想起了「新的」弱類型語言,當你看它這樣...
這沒有任何與真正的原因。對'contains'和也許'remove'進行某種類型的檢查會更好。這本來就不太容易出錯。 – 2010-06-08 01:38:29
「它總會返回錯誤」不,它不會。一個班級完全有可能爲另一個班級的對象設置一個對象 – newacct 2010-06-08 02:01:46
在這裏找到答案。
Why aren't Java Collections remove methods generic?
總之,他們想要最大限度地提高向後兼容性,因爲集合早在泛型之前就已經被引入。
並從我身上添加:他所指的視頻值得一看。
http://www.youtube.com/watch?v=wDN_EYUvUq0
更新
爲了澄清,該名男子誰說(視頻)是誰更新的Java地圖和集合使用泛型的人之一。如果他不知道,那麼誰。
因爲否則它只能與參數類型的完全匹配進行比較,特別是通配集合將停止工作,例如,
class Base
{
}
class Derived
extends Base
{
}
Collection< ? extends Base > c = ...;
Derived d = ...;
Base base_ref = d;
c.contains(d); // Would have produced compile error
c.contains(base_ref); // Would have produced compile error
編輯
對於誰覺得這是不是一個原因持懷疑態度,這是一個帶將泛型修改數組列表包含方法
class MyCollection<E> extends ArrayList<E>
{
public boolean myContains(E e)
{
return false;
}
}
MyCollecttion< ? extends Base > c2 = ...;
c2.myContains(d); // does not compile
c2.myContains(base_ref); // does not compile
基本上contains(Object o)
是一個黑客,使這個非常常見的用例與Java Generics一起工作。
小心解釋downvote? – 2010-06-08 13:13:08
在正常情況下,沒有人會想將一個集合轉換爲'Collection <?在元素操作期間擴展Foo>'。如果是這種情況,'add(E e)'方法也會失敗。 – Jai 2017-08-23 06:06:57
@Jai。這是一個場景'void myMethod(Collection <?extends Foo> coll)'。如果在這裏你需要看看這個集合中是否包含'Foo'的某個版本,那麼你會達到這個答案中描述的限制。 – 2017-09-13 17:29:10
」那個籃子裏的蘋果是否含有這種橙色?「
顯然不能給出TRUE的答案。但仍有可能:
- 答案是錯誤的。
- 問題不是很好形成,它不應該通過編譯。
collection api選擇了第一個。但第二種選擇也會很有意義。像這樣的問題是99.99%的廢話問題,所以甚至不要問!
這個問題不應該被認爲是不合格的,如果一個例如有兩個水果籃,並想知道一個籃子裏的水果是否與另一個水果相匹配。如果一個人知道一個籃子裏只裝蘋果,一個籃子裏只裝一個橘子,那麼將搜索匹配短路是有意義的,但假設一個籃子只包含蘋果,另一個包含混合水果。先詢問另一個籃子中每個水果的蘋果籃,而不首先驗證其類型,那麼比詢問每個水果之前詢問它是否是蘋果更容易。 – supercat 2012-12-03 18:08:59
在我的例子中,參數已知是橙色的,因此這個問題聽起來很荒謬。在你的例子中,問題是「那一籃子蘋果是否含有這種水果?」,這是合法的。這個用例比較少見。我們可以重新設計API以允許您的問題,同時禁止我的問題,通過限制參數類型爲Apple的超類型。 – irreputable 2012-12-03 19:43:56
在.Net中沒有任何機制可以通過它來限制一個參數,泛型或其他,是一種其他類型的超類型,我不認爲Java也有這樣的機制。這樣的事情往往會違反Liskov替代原則,因爲'Fruit'可用的方法應該可以與'Orange'一起使用。在.Net中有很多方法可以通過哪些方式使用'Obsolete'標籤來觸發編譯器在一些特定的靜態可識別的愚蠢的情況下,但我認爲這會比有幫助的更困惑。 – supercat 2012-12-03 19:56:34
- 1. 爲什麼ArrayList在內部使用Object [](而不是E [])?
- 2. Page_Load(object sender,EventArgs e)---爲什麼「object」不能大寫?
- 3. 爲什麼MySQL將e視爲e?
- 4. 爲什麼ArrayList add()和add(int index,E)的複雜度是攤銷常量時間?爲什麼不是O(1)爲add(),O(n)爲add(int index,E)?
- 5. 爲什麼TreeSet聲明TreeSet <E>而不是TreeSet <E extends Comparable <E>>
- 6. 爲什麼math.Pow10(e int)返回float64而不是int64?
- 7. 有人可以解釋e = e || X?爲什麼將e分配給e?
- 8. 爲什麼HashSet的<E>不包含限制參數的類型爲E()和remove()
- 9. css BEM - 我們真的需要E嗎?
- 10. 爲什麼Collection <E> #toArray()不返回E []?
- 11. 是什麼Math.E和e
- 12. 什麼是Bud1%@ @ @ @ E%DSDB` @ @ @?
- 13. base.OnPreInit(e)是什麼意思?
- 14. 「\ e」是什麼意思?
- 15. ActionEvent e是什麼意思?
- 16. gcc -E是什麼意思?
- 17. 我們稱這個圖爲什麼?我們稱之爲E-R圖嗎?
- 18. 爲什麼選擇e?
- 19. <?有什麼區別?擴展Object>和<E extends Object>?
- 20. ps -e -o user:20,pid是什麼意思?
- 21. 爲什麼我返回[Object,object]而不是字符串?
- 22. 爲什麼拓撲排序找到最短路徑O(V + E)
- 23. 爲什麼我們需要鍵入 '( 「+ I +」)',而不僅僅是 '(我)'
- 24. 爲什麼List接口的lastIndexOf()方法接受Object作爲參數而不是E?
- 25. 我應該如何在html中包含√E?我想水平登錄E
- 26. <E>是什麼意思集合<E>?
- 27. e => new EmployeeSummary {Employee = e}是什麼意思?
- 28. '\ e [s'和'\ e [u'字符序列是什麼?
- 29. Javascript e vs. object? Chome Inspector
- 30. 爲什麼會有人做Catch(Exception e){throw e; }?
可能的重複[爲什麼不是Java集合刪除方法通用?](http://stackoverflow.com/questions/104799/why-arent-java-collections-remove-methods-generic) – newacct 2010-06-08 02:18:48