更新:我问了一个愚蠢的问题,我混合B是A的子类型,然后Map<String, B>
也是Map<String, A>
的子类型,这显然是不正确的。
public interface A { .... }
public class B implements A {
....
}
现在我有了这门课。
Class abstract ABC {
public abstract Map<String, A> execute();
}
Class XYZ {
private ABC abc;
public Map<String, A> doSomeWork(){
return abc.execute()
}
}
然后
Class DEF extends ABC {
@Override
public Map<String, B> execute(){
....
}
}
Class Main {
....
XYZ xyz = new XYZ();
DEF def = new DEF();
xyz.setABC(def);
Map<String, B> map = xyz.doSomeWork(); //incompatible type error here
....
}
这是我使用通用地图完全错误的方式吗?我想要的是 doSomeWork 方法可以相应地返回不同类型的地图,我试图将返回类型更改为Map<String, ? extends A>
,但这也不起作用。
我可能不会澄清问题,我已经更新了遗漏的细节。
答案 0 :(得分:5)
假设您有一个额外的class C implement A
。
public Map<String, A> doSomeWork()
将允许您返回包含实现A
的任何值的映射,即一堆B
个实例以及C
个实例。
你被允许做Map<String, B> map = doSomeWork();
你假设所有的值都是B
个实例,这些实例可能不是真的,因此你会遇到令人讨厌的惊喜。由于编译器不希望您以这种方式感到惊讶,因此它从一开始就抱怨/警告/拒绝编译。
为什么Map<String, ? extends A> doSomeWork()
不起作用?该签名将允许您返回Map<String, A>
或Map<String, C>
,我希望您可以看到如何将Map<String, B>
分配到您的代码中。
那你能做什么?
doSomeWork()
返回实现A
的任何值类型的地图并且只使用Map<String, A> map = doSomeWork()
。doSomeWork( B.class )
。该方法可能如下所示:
public <T extends A> Map<String, T> doSomeWork( Class<T> valueType ){
....
}
Map<String, B> map = doSomeWork( B.class );
Map<String, C> anotherMap = doSomeWork( C.class );
答案 1 :(得分:1)
如果execute
的返回类型因ABC
的实施而发生变化,您可以ABC
通用:
abstract class ABC<T extends A> {
public abstract Map<String, T> execute();
}
class XYZ<T extends A> {
private ABC<T> abc;
public Map<String, T> doSomeWork(){
return abc.execute();
}
}
class DEF extends ABC<B> {
@Override
public Map<String, B> execute(){
....
}
}
然后:
XYZ<B> xyz = new XYZ<>();
DEF def = new DEF();
xyz.setABC(def);
Map<String, B> map = xyz.doSomeWork();