继this question之后,它提供了一个解决方案,但没有解释它(不幸的是,答案中的链接现在已经死了):
采取以下方法:
void method(Map<?, ?> myMap) {
Set<Map.Entry<?, ?>> set = myMap.entrySet();
...
}
简单,不是吗?但是,这无法在jdk1.7.0_25上编译:
incompatible types required: java.util.Set<java.util.Map.Entry<?,?>> found: java.util.Set<java.util.Map.Entry<capture#1 of ?,capture#2 of ?>>
WTF? Map.entrySet()
被指定为返回Set<Map.Entry<K, V>>
类型的对象,因此在上面的示例中,myMap.entrySet()
会返回Set<Map.Entry<?, ?>>
。但它没有编译!
甚至更奇怪,从顶部的链接问题,将方法更改为此使得它编译:
void method(Map<?, ?> myMap) {
Set<? extends Map.Entry<?, ?>> set = myMap.entrySet();
...
}
WTF ??? 在entrySet
上拨打Map<?, ?>
会返回Set<Map.Entry<K, V>>
,但无法分配给Set<Map.Entry<K, V>>
Set<? extends Map.Entry<K, V>>
类型的变量,但它可以是? extends ...
类型的变量?????
任何人都可以了解这里发生的事情吗?这是否意味着,每当我使用至少2级深度的通配符类型编写方法时,我必须记得在某处将其设为{{1}}?
答案 0 :(得分:6)
每个人?可以独立变化,因此无法保证<?,?>
声明中的myMap
与<?,?>
声明中的set
匹配。
这意味着,一旦我有Set<Map<?,?>>
,我就可以将任何类型的Map
放入该集合中,因为Map<?,?>
是一个超类型所有类型的Map
。但这不是Set<Map<String,Integer>>
(例如)所具有的属性 - 就我可以放入哪种类型的地图而言,它的限制性要大得多。所以Set<Map<?,?>>
不是Set<Map<String,Integer>>
的超类型。但myMap.entrySet()
可能很容易成为Set<Map<String,Integer>>
,具体取决于myMap
。Set<Map<?,?>>
。所以编译器必须禁止我们将它分配给Set<? extends Map<?,?>>
类型的变量,这就是发生的事情。
另一方面,Set<Map<String,Integer>>
是Map<String,Integer>
的超类型,因为Map<?,?>
是myMap.entrySet()
的子类型。因此,可以将Set<? extends Map<?,?>>
分配给String
类型的变量。
请注意,此处Integer
和myMap
没有什么特别之处,但<K, V> void method(Map<K, V> myMap) {
Set<Map.Entry<K, V>> set = myMap.entrySet();
...
必须是的地图!
你可以写
{{1}}