2013-10-08 38 views
6

我有一個關於Java泛型的問題。說我有以下接口:Java - 泛型和通配符&接口與實現

public static class Something<T> { 
    public void set(T t) { 
    } 
} 

public static interface Manager<T> { 
    public void add(final String key, final Something<T> o); 

    public Something<T> get(final String key); 
} 

用法的例子:

final Manager<Number> m = ...; 

m.add("key", new Something<Number>()); 
m.get("key").set(new Integer(5)); 

我也想能夠添加Something<Integer>Something<Double>,...到一個Manager<Number>。我會說我必須改變添加功能的簽名:

public static interface Manager<T> { 
    public void add(final String key, final Something<? extends T> o); 

    public Something<T> get(final String key); 
} 

final Manager<Number> m = ...; 

m.add("key", new Something<Integer>()); 
m.get("key").set(new Integer(5)); 

到目前爲止,這麼好。讓我們看一可能實施方案經理:

public static class ManagerImplementation<T> implements Manager<T> { 
    protected HashMap<String, Something<T>> map = new HashMap<String, Something<T>>(); 

    public void add(final String key, final Something<? extends T> o) { 
     map.put(key, o); // <--- here 
    } 

    public Something<T> get(final String key) { 
     return map.get(key); 
    } 
} 

這種失敗,因爲你不能一個Something<? extends T>添加到Map<X, Something<T>>。因此,讓我們改變這一點:

public static class ManagerImplementation<T> implements Manager<T> { 
    protected HashMap<String, Something<? extends T>> map = new HashMap<String, Something<? extends T>>(); 

    public void add(final String key, final Something<? extends T> o) { 
     map.put(key, o); 
    } 

    public Something<T> get(final String key) { 
     return map.get(key); // <--- here 
    } 
} 

這將失敗,因爲map.get(key)回報Something<? extends T>而一開始的功能需要返回Something<T>,如在接口中定義。

解決此問題的常用方法是什麼?

謝謝!

+0

爲什麼你不能改變get方法在界面上'公共的東西 GET(最終String鍵);'呢? –

+1

@HariShankar這將返回'Something ',所以OP將無法通過這樣的引用(除'null')設置任何東西。 – Pshemo

回答

3

在課堂內部,您總是使用Something<? extends T>,因此在您的public get方法中,您必須將內部世界轉換爲外部世界格式。例如。你可以簡單地投map.get(key)Something<T>結果:

return (Something<T>) map.get(key); // <--- here 
+0

我對泛型相當陌生。我一直有這樣的想法,即在泛型到位時可以避免施放。所以這不是真的?這隻能通過使用演員才能正確解決? – user1284566

+0

從實際的角度來看,我的建議是:使用泛型,但使用稀疏。通常,一種泛型(如'',不擴展或超級)就足夠了,一切都更加複雜,並使您的代碼變得不可讀。強調'通常'。 ;-) – LastFreeNickname

+0

因此,換言之,對於外部世界/ API,泛型必須符合預期(必要時使用通配符),但對於實現而言,最好儘可能簡單? – user1284566