【发布时间】:2021-02-22 19:39:38
【问题描述】:
直奔主题(我知道应该避免使用wildcard types as the returning type)
我正在写这个answer 和以下代码:
public static Map<?, Long> manualMap(Collection<?> c){
Map<?, Long> map = new HashMap<>();
c.forEach(e -> map.compute(e, (k, v) -> (v == null) ? 1 : v + 1));
return map;
}
收到以下警告:
Required type: capture of ?
Provided: capture of ?
以及来自 IntelliJ 的建议
将变量 'map' 更改为 'Map, Object'
这更没有意义。自然,当我尝试应用该建议时它会失败。
最初,我认为“好吧,这与它与计算签名不匹配这一事实有关”,即:
default V compute(K key, ...)
所以我尝试了
public class MyMap <T>{
public static <T> void nothing(Collection<T> c){
// Empty
}
}
和
public static Map<?, Long> manualMap(Collection<Collection<?>> c, Map<?, Long> map){
c.forEach(MyMap::nothing);
return map;
}
我没有问题。
以下两个版本:
public static <T> Map<?, Long> manualMap(Collection<?> c){
Map<T, Long> map = new HashMap<>();
c.forEach(e -> map.compute((T) e, (k, v) -> (v == null) ? 1 : v + 1));
return map;
}
和
public static Map<?, Long> manualMap(Collection<?> c){
Map<Object, Long> map = new HashMap<>();
c.forEach(e -> map.compute(e, (k, v) -> (v == null) ? 1 : v + 1));
return map;
}
工作没有任何问题(除了(T)情况下的警告)。
所以问题是
为什么第一个版本不起作用?
【问题讨论】:
-
map.compute(e, ...)的问题与List<?> anyList;anyList.add(whateverNonNullValue)的问题相同(错误)。由于anyList可以保存任何列表,例如List<Integer>List<String>List<Cat>,Java 不能保证添加元素总是安全的。因此,当从List<?>调用像List#add(T element)这样的任何方法时,它的T element实际上是? element,并且唯一可以分配给它的安全值是null。即使您尝试使用anyList1.add( anyList2.get(0) ),anyList2.get(0)也会被删除为Object,这也不安全。 -
@Pshemo 感谢您的评论