为什么这个演员有效?
import java.util.HashMap;
import java.util.Map;
public class TestMap {
public static void main(String[] args) {
Map<String, Map<String, Map<String, Map<String,Integer>>>> resultMap = new HashMap<>();
Map<String, Object> aMap = new HashMap<String, Object>();
Map<String, Integer> hiddenMap = new HashMap<String, Integer>();
hiddenMap.put("fortytwo", 42);
aMap.put("key", hiddenMap);
resultMap = (Map<String, Map<String, Map<String, Map<String, Integer>>>>) aMap.get("key");
System.out.println(resultMap);
}
}
也是这样:
Map<String, Map<String, Map<String, Map<String,Map<String,Integer>>>>> resultMap = new HashMap<>();
...
resultMap = (Map<String, Map<String, Map<String, Map<String,Map<String,Integer>>>>>) aMap.get("key");
依旧......
如果Map<String, Integer>
隐藏地图成功投放到Map<String, Map<String, Map<String, Map<String,Integer>>>> resultMap
,会如何发生这种情况?
始终打印:
{fortytwo=42}
这也适用(地图而不是地图):
public static void main(String[] args) {
Map<String, Map<String, Map<String, Map<String,Map<String,Integer>>>>> resultMap = new HashMap<>();
Map<String, Map> aMap = new HashMap<String, Map>();
Map<String, Integer> hiddenMap = new HashMap<String, Integer>();
hiddenMap.put("fortytwo", 42);
aMap.put("key", hiddenMap);
resultMap = (Map<String, Map<String, Map<String, Map<String,Map<String,Integer>>>>>) aMap.get("key");
System.out.println(resultMap);
}
编辑:正如@shizhz所说,这是因为类型擦除当然!所以上面的代码相当于:
Map resultMap = new HashMap();
Map aMap = new HashMap();
Map hiddenMap = new HashMap();
hiddenMap.put("fortytwo", 42);
aMap.put("key", hiddenMap);
resultMap = (Map) aMap.get("key");
哪个也有效
答案 0 :(得分:4)
因为在编译时使用java泛型来提供更严格的类型检查,所以编译器会根据Type Erasure rules删除type参数:
在代码Map<String, Map> aMap = new HashMap<String, Map>();
中,aMap
中的值是原始类型Map
,这意味着当您尝试使用时,编译器不知道它包含的类型是什么将原始类型的Map
转换为Map
的任何泛型类型,如Map<String, Integer>
,最好的编译器可以做的就是给你一个警告。泛型类型在编译时被擦除,并且当您从通用映射获取值时将生成类型转换,因此如果类型不匹配,您只能获得运行时 ClassCastException
异常。
让我们看看下面的例子:
public static void main(String[] args) {
Map map = new HashMap();
map.put("hello", "world");
map.put(new Integer(1), 1);
map.put(new Object(), Lists.newArrayList("hello"));
Map<String, Integer> m = (Map<String, Integer>) map;
System.out.println(m);
Integer i = m.get("hello");// ClassCastException happens at here at runtime
}
我尝试将包含各种键和值的Map
转换为Map<String, Integer>
但是没有编译错误,在类型擦除后,上面的代码实际上是等效的到:
public static void main(String[] args) {
Map map = new HashMap();
map.put("hello", "world");
map.put(new Integer(1), 1);
map.put(new Object(), Lists.newArrayList("hello"));
Map m = (Map) map;
System.out.println(m);
Integer i = (Integer)m.get("hello");
}
现在,您可以轻松地说明为什么最后一行导致了ClassCastException
。
答案 1 :(得分:3)
由于您已将aMap
声明为Map<String, Object>
,因此编译器无法判断这些值是否确实属于Map<String, Map<String, Map<String,Integer>>>
类型。它会给你一个“未经检查的演员”警告,让你考虑后果。
resultMap.get("fortytwo").isEmpty();
将导致
Exception in thread "main" java.lang.ClassCastException:
java.lang.Integer cannot be cast to java.util.Map
如果您已将aMap
声明为Map<String, Map<String, Map<String, Map<String, Map<String, Integer>>>>>
,则您首先无法将hiddenMap
放入其中。