2010-04-06 119 views
3

是否可以將嵌套泛型/捕獲綁定在一起?是否可以綁定嵌套泛型?

我經常會遇到將類映射到泛型項目的問題。具體而言,我想要這樣的東西(不,T沒有在任何地方聲明)。

private Map<Class<T>, ServiceLoader<T>> loaders = Maps.newHashMap(); 

總之,我想loaders.put /得到具有語義的類似:

<T> ServiceLoader<T> get(Class<T> klass) {...} 
<T> void put(Class<T> klass, ServiceLoader<T> loader) {...} 

是下面我能做的最好的?我是否必須忍受不可避免的@SuppressWarnings("unchecked")下線?

private Map<Class<?>, ServiceLoader<?>> loaders = Maps.newHashMap(); 
+0

您是否嘗試過?結果是什麼? (我以前沒有嘗試過這樣的事情,但是我會很好奇,知道它是否可以在盒子裏使用?) – Edmund 2010-04-06 08:56:21

+0

可悲的是,它不起作用。我想知道是否有人想出瞭解決辦法。目前我正在使用雙重捕捉和@SuppressWarning。 – 2010-04-06 10:10:55

回答

6

讓我看看,如果我得到你的意圖:你想有一個地圖存儲的Class /ServiceLoader對其中每對由同一T參數,但T可以是跨不同的對?

如果是這種情況,那麼最好的解決方案是聲明你自己的類,它將展現這樣一個接口。它在內部將它們存儲在通用的Map<Class<?>,ServiceLoader<?>>地圖中。

public class MyMap { 
    private Map<Class<?>, ServiceLoader<?>> loaders 
     = new HashMaps<Class<?>, ServiceLoader<?>>(); 

    public<T> void put(Class<T> key, ServiceLoader<T> value) { 
     loaders.put(key, value); 
    } 

    @SuppressWarnings("unchecked") 
    public<T> T get(Class<T> key) { return (ServiceLoader<T>) loaders.get(key); } 
} 

@SuppressWarnings("unchecked")註釋並非純粹的邪惡。你應該儘量避免它們,但是在某些情況下,儘管事實上編譯器看不到這些,你仍然可以發現轉換是正確的。

+0

+1,但key.cast()僅在值類型爲T時纔有效.Josh Bloch在「Effective Java」中稱這種「Typesafe Heterogeneous Container Pattern」。我通常在put方法中寫入loaders.put(key,key.cast(value)),然後如果用戶以某種方式繞過編譯時檢查,則在添加值時會彈出錯誤,而不是在檢索時彈出錯誤。 – Yardena 2010-04-06 13:34:13

+0

@Yardena - 你說的沒錯。我忽略了這一點。 @SuppressWarnings無法避免,畢竟 – 2010-04-06 14:45:41

0

我的建議是爲這種情況創建一個新的對象。我看到你正在使用Maps.newHashMap(),所以我認爲你使用了谷歌番石榴,所以我會用ForwardingMap

public class Loader<T> extends ForwardingMap<Class<T>, ServiceLoader<T>> { 

    private Map<Class<T>, ServiceLoader<T>> delegate = Maps.newHashMap(); 

} 

一個簡單的測試證明,我的建議是工作:

public class Loader<T> extends ForwardingMap<Class<T>, Class<T>> { 

    private Map<Class<T>, Class<T>> delegate = Maps.newHashMap(); 

    @Override protected Map<Class<T>, Class<T>> delegate() { 
     return delegate; 
    } 

    public static void main(String[] args) { 
     Loader<Integer> l = new Loader<Integer>(); 

     l.put(Integer.class, Integer.class); 

     // error 
     l.put(Integer.class, String.class); 
    } 

} 
+0

我希望T在Key/Value對之間是相同的;沒有穿過整個系列。 – 2010-04-06 16:22:01