为什么这个转换有效?
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 是Map<String, Integer>
,这是怎么发生的?成功转换为 Map<String, Map<String, Map<String, Map<String,Integer>>>> resultMap
?
总是打印:
{fortytwo=42}
这也有效( map 而不是 map ):
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");
这也行
最佳答案
因为在编译时使用 java 泛型来提供更严格的类型检查,编译器根据 Type Erasure rules 删除类型参数:
- 如果类型参数是无界的,则将泛型类型中的所有类型参数替换为它们的边界或 Object。因此,生成的字节码仅包含普通类、接口(interface)和方法。
- 必要时插入类型转换以保持类型安全。
- 生成桥接方法以在扩展泛型类型中保留多态性。
在代码中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
.
关于嵌套映射的 Java 显式转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43412121/