通用返回类型 - 为什么我不能这样做?

时间:2012-11-27 19:25:10

标签: java generics inheritance return-type

考虑下面的代码段。我理解有关泛型类型的重写方式,以及为什么允许返回类型List<String>(例如)覆盖List<? extends Object>。但是,我不完全清楚为什么诸如1和2之类的语句无法编译......这里是否也不应该继承继承?

public class Generics {

    public static void main(String[] args) {

        A instance = new B();
        X instance2 = new Y();

        Map<String, String> map = instance2.getMap(); // 1
        List<String> list = instance.getList();       // 2
    }
}

class A {

    List<? extends Object> getList() {

        return null;
    }
}

class B
        extends A {

    List<String> getList() {

        return new LinkedList<String>();
    }
}

class X {

    Map<String, ? extends Object> getMap() {

        return null;
    }
}

class Y
        extends X {

    @Override
    Map<String, String> getMap() {

        return null;
    }
}

3 个答案:

答案 0 :(得分:3)

Map<String, String> map = instance2.getMap(); // 1

编译器看到对X.getMap()的调用,其返回类型为Map<String, ? extends Object>。这不能转换为Map<String, String>instance2在运行时类型为Y并不重要;这是纯粹的编译时静态类型检查失败。

List<String> list = instance.getList();       // 2

同样的理由适用。编译时类型instanceAA.getList()返回List<? extends Object>,与List<String>不兼容。

请注意,这不是特定于泛型的问题。由于同样的原因,这也无法编译:

class A { Object getObject(); }
class B extends A { String getObject(); }

A a = new B();
String s = a.getObject();

如果您希望它能够工作,那么您需要为编译器提供一些额外的帮助。通过投射到子类:

String s = ((B) a).getObject();

或者通过转换返回值:

String s = (String) a.getObject();

答案 1 :(得分:1)

多态性不能倒退。

如果您尝试使用扩展X的其他类,但是它返回给您了

,该怎么办?
Map<String, NonString>

代替?

答案 2 :(得分:0)

您在getMap上呼叫X(因为instance2是引用者通过X),这被定义为返回Map<String, ? extends Object>因此问题。

如果您在致电instance2之前将通话更改为(YgetMap()):

   Map<String, String> map = ((Y)instance2).getMap(); // 1

它应该有效,因为instance2仍然是Y类型。