我必须在下面的 map 中放置一个整数值.
Map<String,?> map
map.put("key",2000);
当我运行上述代码时,我得到以下错误:
incompatible types: java.lang.Integer cannot be converted to capture#1 of ?
我必须在下面的 map 中放置一个整数值.
Map<String,?> map
map.put("key",2000);
当我运行上述代码时,我得到以下错误:
incompatible types: java.lang.Integer cannot be converted to capture#1 of ?
Unbounded个通用集合(Collection<?>
个)是not writable个.让我们来探究原因.
方括号<?>
中的问号称为unknown type.对于编译器来说,这意味着actual type不能被预测,在运行时它可能看起来非常匹配任何东西:Object
、String
、Cat
.因此,从unbounded collection中检索到的所有内容都将被视为Object
:
Collection<?> items = new ArrayList<>();
Object item = items.iterator().next(); // this assignment is safe and will compile
但是don't confuse是unbounded collection加collection of objects.他们是incompatible.
Collection<Object>
有invariant behavior个,也就是说,它只希望再分配collection个Object
类型.同时,我们可以将any类型的集合分配给Collection<?>
.
Collection<?> items = new ArrayList<String>(); // OK
Collection<Object> objects = items; // that will not compile
Collection<Object> objects = new ArrayList<String>(); // that will not compile
所以unknown type可以用extendsObject
表示.你可能会认为Collection<?>
就像是upper-bounded系列Collection<? extends Object>
.他们绝对是compatible岁.
Collection<?> items = new ArrayList<>();
Collection<? extends Object> upperBounded = items; // no issues
items = upperBounded; // no issues
像<?>
或<? extends Object>
这样的通配符是not actual types.它们只是告诉编译器我们不知道type在运行时是什么.
那么百分之一百零一是什么呢?
因为已经很清楚unknown type(<?>
)意味着any type可以延伸到Object
,因此在Collection<?>
的引擎盖下可能会出现ArrayList<Object>
、ArrayList<String>
、HashSet<BigDecimal>
等等.
因为在ArrayList<String>
中加Object
,或者在HashSet<BigDecimal>
编译器中加String
都是illegal,所以任何试图在Collection<?>
中加任何东西的try 都是prevent.没有与unknown type兼容的类型.
只有一个例外,null
是任何类型对象的有效值,因此可以将其添加到unbounded和upper-bounded集合中.
Collection<?> items = new ArrayList<>();
items.add(null);
System.out.println(items);
items.remove(null);
System.out.println(items.isEmpty());
将给出output分:
[null] - null-element was successfuly added
true - i.e. isEmpty
Note:对于unbounded和upper-bounded个集合,removal个元素都有no个限制.
因此,有no way个新条目要添加到unbounded map,你可以一个接一个地复制它的条目,执行instanceOf
判断到常规的泛型映射Map<String, Integer>
,通过将映射分配给变量row type来消除泛型,然后在需要检索value时手动添加type-casts,如Java 1.4.
这就是如何将unbounded map的内容复制到regular,并利用泛型的优势.
Map<String, ?> unboundedMap = new HashMap<>()
Map<String, Integer> writableMap = new HashMap<>();
for (Map.Entry<String, ?> entry: unboundedMap.entrySet()) {
if (entry.getValue() instanceof Integer) {
writableMap.put(entry.getKey(), (Integer) entry.getValue());
}
}
使用流API也是一样的
Map<String, Integer> writableMap =
unboundedMap.entrySet().stream()
.filter(entry -> entry.getValue() instanceof Integer)
.collect(Collectors.toMap(Map.Entry::getKey,
entry -> (Integer) entry.getValue()));