考虑下面的代码段。我理解有关泛型类型的重写方式,以及为什么允许返回类型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;
}
}
答案 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
同样的理由适用。编译时类型instance
为A
,A.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
之前将通话更改为(Y
至getMap()
):
Map<String, String> map = ((Y)instance2).getMap(); // 1
它应该有效,因为instance2
仍然是Y
类型。