2012-11-07 90 views
1

我有以下的(這種形式顯然是無用)的Java類:Java類型捕獲的內部類

public class EntrySet<T> { 

    public static class Entry<T> { 
     T obj; 
    } 

    private final Set<Entry<T>> set; 

    public EntrySet() { 
     this.set = Sets.newHashSet(); 
    } 

    public Set<Entry<T>> getEntries() { 
     return set; 
    } 
} 

鑑於這個類,下面不編譯:

EntrySet<?> entrySet = new EntrySet<SomeClass>(); 
Set<EntrySet.Entry<?>> entries = entrySet.getEntries(); 

第二行編譯錯誤「無法從Set<EntrySet.Entry<capture#1-of ?>>轉換爲Set<EntrySet.Entry<?>>」。我無法找到消除此錯誤的方法,即使在投射或使用助手功能時也是如此。

究竟什麼是這裏的問題,是有沒有辦法得到一個乾淨的編譯?

我能做到的最好的是:

EntrySet<?> entrySet = new EntrySet<SomeClass>(); 
Set<?> tmp = entrySet.getEntries(); 
Set<EntrySet.Entry<?>> entries = (Set<EntrySet.Entry<?>>) tmp; 

這顯然是可怕的(即使有相關的警告抑制)。

+0

您是否嘗試過EntrySet entrySet = new EntrySet (); ? – Jerome

+0

這只是一些虛擬代碼,以確保問題清楚。這當然會起作用,但就我而言,我所擁有的只是一個'EntrySet '。 – Carl

回答

1

刪除entrySet您正試圖將Set<EntrySet.Entry<SomeClass>>指定爲Set<EntrySet.Entry<?>>。有幾百個Stack Overflow問題基本上是相同的。你可以給後者增加一個EntrySet.Entry<OtherClass>,但不是前者,這樣就會破壞類型安全。

可能是對付這種方式是通過調用一個(命名)泛型參數的方法來捕捉野生卡。

EntrySet<?> entrySet = new EntrySet<SomeClass>(); 
    fn(entrySet); 
... 
private static <T> void fn(EntrySet<T> entrySet) { 
    Set<EntrySet.Entry<T>> entries = entrySet.getEntries(); 
+0

不能添加'EntrySet.Entry ''來設置>'。你不能添加*任何*到它。 –

+0

我不確定我是否按照這個問題行事。正如@MiserableVariable所說的,你不能插入一個'Set >'。例如,編寫'Map map = new HashMap ();'後面跟着'Set keys = map.keySet();'完全可以。關於通配符嵌套的事實是有所不同的,雖然它肯定有點像你說的,但我沒有看到它。 – Carl

+0

我相信你可以添加到'Set >'(沒有得到安裝在這臺機器上的Java來檢查)。 /我想'入口'聲明爲'設置<?擴展EntrySet.Entry >'也將工作(對於某些目的)。 –

0

無界通配符<?>就像所有泛型類型的超類型。它與所有Java類的Object類相似。可以在無界的通配符參考執行的操作只有那些採取「空」(如果<?>參數在參數參考使用)或那些返回一個「物件」(如果<?>參數在返回類型參考使用)。因此,如果您的代碼返回Object類型的引用,它將進行編譯。

class EntrySet<T> { 

    public static class Entry<T> { 
     T obj; 
    } 

    private final java.util.Set<Entry<T>> set; 

    public EntrySet() { 
     this.set = new java.util.HashSet(); 
    } 

    public java.util.Set<Entry<T>> getEntries() { 
     return set; 
    } 

    public static void main(String [] args){ 
     EntrySet<?> entrySet = new EntrySet<SomeClass>(); 

    //java.util.Set<EntrySet.Entry<?>> entries = entrySet.getEntries(); // Error 

     Object o = entrySet.getEntries();   // OK ! 
    } 
} 

class SomeClass{}