为什么我无法返回通用地图?

时间:2017-03-13 14:51:39

标签: java generics interface

更新:我问了一个愚蠢的问题,我混合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>,但这也不起作用。

我可能不会澄清问题,我已经更新了遗漏的细节。

2 个答案:

答案 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();