2013-10-08 59 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