Объяснение
Вы интерпретируете свои результаты немного неправильно. Вы говорите, что он печатает
[0, 0]
и заключаете, что у вас есть два ключа типа Long
со значением 0
. Но это на самом деле неправильно. Один действительно Long
, идущий отсюда:
blockMap.put(0L, i);
Но другой - String
"0"
, который в печати выглядит так же.
Raw-types
Вы можете быть смущены, почему в вашем HashMap<Long, Block>
есть строковый ключ. В конце концов, он определяет ключ как Long
, а не как String
.
Проблема здесь:
Map map = gson.fromJson(json, Map.class);
blockMap.putAll(map);
Здесь происходит то, что вы используете putAll
, но предоставить Map
. Обратите внимание, что у него нет генериков, это необработанный тип .
Используя необработанный тип, вы в основном жертвуете всеми типами безопасности и обещаниями Java "Да, да, поверь мне, я знаю, что делаю. Так что Java будет просто доверять вам, что вы на самом деле даете ему Map<Long, Block>
, но вы на самом деле даете ему Map<String, String>
.
Загрязнение кучи
В Java , генерики стираются во время выполнения . Это означает, что после прохождения компиляции Java больше ничего не знает о дженериках и, в основном, позволяет вам смешивать типы так, как вы хотите, это просто "Map<Object, Object>
" более или менее.
Так что вам удалось обмануть Javas safe generi c -type-system и добавили String
в карту, которая принимает только Long
s в качестве ключей. Это называется куча загрязнений . И это главная причина, почему вы никогда не должны использовать raw-типы. Использование raw-типов бесполезно.
Небольшой пример загрязнения кучи:
List<Dog> dogs = new ArrayList<>(); // safe collection
dogs.add(new Dog());
// dogs.add(new Cat()); // not allowed, dogs is safe
List raw = dogs; // raw handle to safe collection
raw.add(new Cat()); // works! heap pollution
// compiles, but throws at run-time,
// since it is actually a cat, not a dog
Dog dog = dogs.get(1);
Примечания
Подробнее об этой теме читайте здесь c: