2012-01-31 56 views
0

接受泛型集合中的子類型

我試圖找到一種方法,在該方法中我可以返回一個通用集合,它將接受子類型。下面的代碼返回Set<? extends A>,我試圖添加B

import java.util.Set; 
import java.util.HashSet; 

public class Test { 
    private static class A {} 
    private static class B extends A {} 

    public Set<? extends A> getSet() { 
     return new HashSet<B>(); 
    } 

    public void work() { 
     getSet().add(new B()); // compile error 
    } 
} 

這將導致以下錯誤:

Test.java:13: cannot find symbol 
symbol : method add(Test.B) 
location: interface java.util.Set<capture#320 of ? extends Test.A> 
       getSet().add(new B()); 

generic wildcard tutorial指出B不能被添加到Set<? extends A>,因爲我們不知道,如果BA一個亞型,但我只是定義爲這樣。有人能爲我澄清這一點嗎?

回答

5

這是根本不可能的。

如果該方法實際返回一個HashSet<C>會怎麼樣?
您剛添加B到一組C s。

檢查類型安全時忽略該方法的內容(return語句)。

如果你想這樣做,你應該只是返回一個普通的HashSet<A>

+0

我認爲這個想法是,在一組'C'中添加'B'會引發錯誤,因爲'B'不會擴展'C'。這可能是不可能的,因爲它在編譯時不能被知道。 – paislee 2012-01-31 19:39:30

+0

你是對的,我沒有考慮過。說實話,這是我遇到的問題的一個蒸餾版本。我會找到另一種方式。 – KennethJ 2012-01-31 19:42:58

0

問題的關鍵在於,您可以以這種方式使用通配符遍歷擴展公共父項並執行讀取操作的不同對象,但如果要寫入集合,則不起作用。

原因是編譯器無法確定將從getSet()方法返回的集合的運行時類型。它不會解析你所寫的代碼,並試圖達成該決定。

0

The generic wildcard tutorial states that B cannot be added to a Set<? extends A> because we don't know if B is a subtype of A, but I have just defined it as such.

這並不完全正確。說B和C每個擴展一個。 getSet()方法可能返回一組B或一組C.您不知道。所以你不能只給它添加Bs。它可能是一組C並且會打破合同。

做的問題不在於你不知道B是A的一個子類型,而是你不知道A的哪個子類型?是。

+0

呵呵。所有人都一樣的答案:) – PaulMurrayCbr 2012-02-03 03:26:30