Бросок ClassCastException
правильный. Отсутствие этого было вызвано ошибкой в javac
, которая была исправлена в JDK 9 с помощью JDK-8058199 . Ваш код технически полагается на то, что загрязнение кучи не выявляется, поэтому он никогда не гарантированно не сломался.
По сути, в Java 11 (но начиная с 9) добавляется дополнительное приведение после получения значения для "LongNumber"
из карты от второй до последней строки. Это:
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;
Обратите внимание, что после 120:
нет инструкции checkcast
. Однако при использовании 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;
Обратите внимание, что в 125:
.
есть инструкция
checkcast
.
Эта инструкция имеет значение, так как она в основном выполняет дополнительную проверку типов после получения значения из карты versionDoc
. В основном это делается:
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
. Разница лишь в том, что есть дополнительный тип для проверки типа после получения значения с карты.
Обратите внимание, что отсутствующий checkcast
был ошибкой в javac
, поэтому компиляция с использованием другого компилятора или разных версий javac
может привести к другому поведению.