2012-10-09 15 views
6

可能重複:
What are the reasons why Map.get(Object key) is not (fully) generic
Why does Java's TreeSet<E> remove(Object) not take an E爲什麼HashSet的<E>不包含限制參數的類型爲E()和remove()

爲什麼HashSet中沒有限制的類型爭論到E位置:

public boolean contains(Object o) 
public boolean remove(Object o) 

像它爲附加()

public boolean add(E e) 

我的意思是如果編譯器執行只被添加E型的對象,則該集不能包含/移除的任何其它類型

+0

'add'增加了新的元素列表,以便有必要,以確保它是正確的類型。 –

回答

4

不同的是,添加的類型必須是安全的保存收集的完整性,同時項目檢查/移除可以買得起「型赦」在不損害收集的類型安全的風險。換句話說,如果添加一個錯誤類型的元素,該集合將變爲無效;另一方面,如果您檢查是否存在錯誤類型的元素,則只需返回false即可。 remove也是如此:如果您傳遞不兼容類型的元素,則不會在集合+中移除,因此刪除將成爲無操作。


+除非你通過黑客利用類型擦除。

+1

如果傳遞不兼容類型的元素,元素_may仍然在set中 - 請參閱我的答案。 – npe

+1

@npe是的,好的舊式刪除黑客!我更新了答案,提到了這種可能性,但答案的核心仍然是一樣的:界面的通用和非通用方法之間的區別是沿着有害/無害的界線進行的。 – dasblinkenlight

+0

+除非你通過利用類型擦除的黑客入侵,或者它只是等於集合中的一個元素......(詳情請參閱我的回答)。 – DaveFar

2

那麼該組不能包含/刪除任何其他類型

當然可以。閱讀關於type erasure或將您的HashSet<E>轉換爲非通用HashSet,並向其添加非E類型的對象。

看看這個代碼:

Integer testInt = new Integer(3); 

// First, create a generic set of strings 
HashSet<String> set = new HashSet<String>(); 
set.add("abc"); 

// Then make it non-generic and add an integer to it 
((HashSet) set).add(testInt); 

// Now your set-of-strings contains an integer! 
System.out.println(set); // prints: [abc, 3] 

// Remove the integer 
set.remove(testInt); 
System.out.println(set); // prints: [abc] 

這個古怪的原因是泛型類型的信息在運行時被刪除,你的設置變得簡單的一組對象。

+0

'HashSet '你可以添加元素嗎? –

+0

不,你不能。我會糾正答案。 – npe

+0

當你使用?通配符作爲通用參數,你告訴編譯器你有一個實例,通用參數是一些值,但你不知道是什麼。因此,調用該對象上使用該泛型參數的任何方法本質上是不安全的。以HashSet爲例。您可以構造HashSet ,但將其分配給HashSet 編譯器將如何知道參數的類型是什麼?答:它不能。即使通配符有界也是如此(即HashSet <?extends Number>) – Matt

0

你不用向這兩個方法添加任何東西,所以type參數不需要被約束。如果類型不匹配,這些方法可以返回false。

2

containsremove參數不能僅限於E因爲你應該能夠給他們恰好等於對象,這是非常有用的。更確切地說,中HashSet.remove的API說:

...更正式,刪除一個元素e(2 O == NULLé== NULL: o.equals(e)條),如果此集合包含這樣一個元素。

Object.equals需要Object作爲參數,這是還使不同類型之間的平等相當有用的。

因此,要啓用containsremove(關於等價類而不是唯一對象標識)的更一般功能,它們必須以Object作爲參數。


例子:

HashSet<ArrayList<String>> set = new HashSet<ArrayList<String>>(); 
    ArrayList<String> list = new ArrayList<String>(); 
    list.add("foo"); 
    LinkedList<String> equalList = new LinkedList<String>(); 
    equalList.add("foo"); 
    set.add(list); 

    System.out.println(list.equals(equalList)); // prints: true 
    System.out.println(set.contains(equalList)); // prints: true 

    System.out.println(set); // prints: [[foo]] 
    set.remove(equalList); 
    System.out.println(set); // prints: [[]] 
相關問題