我有一段我认为应该编译的代码,但事实并非如此。这是代码:
public class Program {
public void myMethod(List<EnumMap<? extends MyInterface, String>> map)
{
}
public void caller()
{
EnumMap<MyEnum, String> map = new EnumMap<MyEnum, String>(MyEnum.class);
List<EnumMap<MyEnum, String>> list = new LinkedList<EnumMap<MyEnum, String>>();
myMethod(list); //error argument type is not compatible
}
}
MyEnum是一个实现MyInterface的枚举。
为什么调用myMethod(list)会让我的参数类型不兼容?
如果我将myMethod的签名更改为:
public void myMethod(List<? extends Map<? extends MyInterface, String>> map)
然后一切正常,但我仍然感到困惑,并希望知道原来的原因
方法签名不起作用。
答案 0 :(得分:2)
所以,给定
enum MyEnum implements MyInterface { ...}
...
List<EnumMap<MyEnum, String>> as = new ArrayList<EnumMap<MyEnum, String>>();
List<EnumMap<? extends MyInterface, String>> bs;
我们应该可以分配bs = as
?
现在假设
enum OtherEnum implements MyInterface { XXX }
...
EnumMap<OtherEnum, String> otherMap =
new EnumMap<OtherEnum, String>(OtehrEnum.class);
otherMap.put(OtherEnum.XXX, "");
bs.set(0, otherMap);
EnumMap<MyEnum, String> myMap = as.get(0);
MyEnum xxx = myMap.keys().iterator().next();
otherMap
和myMap
指向相同的对象,但明显不同的类型。更糟糕的是,xxx
是tyoe MyEnum
,但指的是OtherEnum
类型的对象。
在存在多态性的情况下指向指针很困难。
答案 1 :(得分:1)
EnumMap<MyEnum, String>
和EnumMap<? extends MyInterface, String>
是不同的类型(前者是后者的子类型)。因此List<EnumMap<MyEnum, String>>
和List<EnumMap<? extends MyInterface, String>>
彼此不兼容。通常,如果A和B是不同的类型,则无法将List<A>
分配给List<B>
,无论A和B之间的关系是什么(同样适用于任何泛型类型而不仅仅是List)。当你有一个有界类型参数时,这是一个不同的故事;兼容性需要考虑范围。