【发布时间】:2020-10-22 15:59:24
【问题描述】:
我希望可以使用任何类型来代替通配符 (?)。
extends 确实如此(如我所料),但 super 编译错误(我不明白为什么它与 extends 示例不同)。
我应该如何看待这种差异 - 这是一个错误还是一个功能?
class Why {
void fSuper(List<? super Map<String,?>> lst) { }
void fExtends(List<? extends Map<String,?>> lst) { }
void test(){
// Why any type instead of ? gives error
fSuper(new ArrayList<Map<String, String>>()); // compile ERR - WHY ???
fSuper(new ArrayList<Map<String, Byte>>()); // c. ERR - WHY ???
fSuper(new ArrayList<Map<String, Map<Short, Boolean>>>()); // c. ERR - WHY ???
fSuper(new ArrayList<Map<String,?>>()); // OK
// Any type instead of ? can be used OK
fExtends(new ArrayList<Map<String, String>>()); // OK
fExtends(new ArrayList<Map<String, Byte>>()); // OK
fExtends(new ArrayList<Map<String, Map<Short, Boolean>>>()); // OK
fExtends(new ArrayList<Map<String,?>>()); // OK
这个问题的灵感来自 pdem here 的回答示例
他的例子似乎和我的 IDE 很不一致
void populateList(List<? super Map<String,?>> list) {
list.clear();
Map<String, String> map;
map = new HashMap<String,String>();
map.put("key", "value"); // compiles
// Map<String, String> for List<? super Map<String,?>>
list.add(map); // compiles !!
}
附注我了解 PECS(生产者扩展/消费者超级)。(请不要因此而关闭问题)。但我没有看到如何在我的第一个代码 sn-p 中使用它。我想我完全理解第二个代码 sn-p。但我不明白为什么ArrayList<Map<String, String>> 没有在我的第一个代码 sn-p 中编译(使用 ...?super)并且在第二个代码 sn-p 中编译并在我的第一个代码 sn-p (with ...? extends)。
我也意识到使用通配符 (?) 通常会带来麻烦(尤其是在违反 PECS 规定的情况下)。
但是我想深入理解泛型,第一个代码sn-p到目前为止比我理解的要好。
【问题讨论】:
-
Map<String, String>是Map<String, ?>的超类型还是子类型?不可能两者兼而有之。唯一同时是类型 T 的超类型和子类型的类型是 T 本身。其他所有类型都是其中一种(或两者都不是)。 -
任何答案对您有帮助吗?