请看我的代码:
Object longL = 2548214;
Map<String, Object> map = new HashMap<String, Object>(1);
map.put("LongNumber", longL);
List<Map<String, Object>> returnlist = new ArrayList(10);
returnlist.add(map);
List<Object> versionMap1 = new ArrayList(10);
versionMap1.add(returnlist);
List<Map<String, String>> docIdVersionNameMap = new ArrayList<>();
docIdVersionNameMap.addAll((List<Map<String, String>>)versionMap1.get(0));
Map<String, String> versionDoc=docIdVersionNameMap.get(0);
Map<String,String> versionDocInfo=new HashMap<String,String>(1);
versionDocInfo.put(versionDoc.get("LongNumber"),"abc");
System.out.println(versionDocInfo.toString());
在 Java_1.8_60(编译和运行)中,此代码运行良好,但在 Java 11 中编译和运行时,它抛出以下异常:
Exception in thread "main" java.lang.ClassCastException: class java.lang.Integer cannot be cast to class java.lang.String (java.lang.Integer and java.lang.String are in module java.base of l
oader 'bootstrap')
at teststringandlong.Trial.main(Trial.java:35)
Java 11 中关于 HashMap 有什么变化吗?
最佳答案
ClassCastException
被扔是正确的。没有抛出它是由 javac
中的错误引起的,已在 JDK 9 中由 JDK-8058199 修复.您的代码在技术上依赖于未被拾取的堆污染,因此无法保证不会中断。
基本上,在 Java 11(但从 9 开始)中,在获取 "LongNumber"
的值后会插入一个额外的转换。从第二行到最后一行的 map 。这:
versionDocInfo.put(versionDoc.get("LongNumber"),"abc");
编译为:
versionDocInfo.put((String) versionDoc.get("LongNumber"),"abc");
使用 javac 1.8.0_162
编译代码时,倒数第二行的字节码是:
114: aload 7
116: aload 6
118: ldc #6 // String LongNumber
120: invokeinterface #16, 2 // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
125: ldc #17 // String abc
127: invokeinterface #7, 3 // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
注意没有 checkcast
120:
之后的说明.但是,当使用 javac 9.0.4
时:
114: aload 7
116: aload 6
118: ldc #6 // String LongNumber
120: invokeinterface #16, 2 // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
125: checkcast #17 // class java/lang/String
128: ldc #18 // String abc
130: invokeinterface #7, 3 // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
注意有一个 checkcast
指令在 125:
.
这条指令有所不同,因为它基本上是在从 versionDoc
获取值后进行额外的类型检查 map 。基本上这样做:
versionDocInfo.put((String) versionDoc.get("LongNumber"),"abc");
在 Java 11(从 9 开始)中。
如评论中所述; "LongNumber"
的值类型是Integer
, 在 Map<String, String>
内由于前面几行未经检查的转换:
docIdVersionNameMap.addAll((List<Map<String, String>>) versionMap1.get(0));
间接转换 Map<String, Object>
的地方到 Map<String, String>
,即使其中一个值是 Integer
.不同之处仅在于在从 map 获取值后有一个额外的转换来检查类型。
请注意缺少 checkcast
是 javac
中的错误,因此使用不同的编译器或不同版本的 javac
进行编译可能会导致不同的行为。
关于java - 使用 HashMap 时 Java 11 中的 ClassCastException 而不是 Java 8 中的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55204967/