为什么要尝试编译
public class GenericsFail {
public static void main(String[] args) {
accept(new HashMap<String, List<String>>());
}
public static void accept(Map<String, List<?>> multiMap) {}
}
Run Code Online (Sandbox Code Playgroud)
给出错误
GenericsFail.java:7: error: method accept in class GenericsFail cannot be applied to given types;
accept(new HashMap<String, List<String>>());
^
required: Map<String,List<?>>
found: HashMap<String,List<String>>
reason: actual argument HashMap<String,List<String>> cannot be converted to Map<String,List<?>> by method invocation conversion
Run Code Online (Sandbox Code Playgroud)
仅当通配符未嵌套在内时才允许使用通配符List.
Boh*_*ian 13
原因是?in List<?>可能是"任何东西",但每个条目中都有不同的 "任何东西" Map.也就是说,它会接受List<String>一个条目,一个条目接受另一个条目List<Integer>.
但是你传递的是每个条目Map中具有相同类型的类型List,因此类型不会以相同的方式或相同的自由度绑定.
"修复"是将类型锁定为特定类型,但仍然是"任何" - 通过键入方法,每个条目中的"任何*" 相同:
public static <T> void accept(Map<String, List<T>> multiMap) // complies
Run Code Online (Sandbox Code Playgroud)
或者如果您的方法确实不需要知道哪种类型,请使用通配符来包装类型:
public static void accept(Map<String, ? extends List<?>> multiMap) // compiles
Run Code Online (Sandbox Code Playgroud)
最后一个版本的工作原理是因为列表的类型虽然是通配符,但在调用时会固定为未知但一致的类型.
我发现键入的版本更容易阅读(和代码),如果您稍后决定您的方法需要知道类型,则可以使用该类型.