Итак, я работаю над плагином для Atlassian Confluence, и в моем контроллере для страницы конфигурации у меня есть HashMap типа HashMap<Integer, String>, которую я заполняю значениями из HTML-формы. Теперь, после отправки формы, я пытаюсь прочитать значение из этого HashMap с помощью .get(key) и сохранить его в String. Я получаю эту ошибку приведения типов: java.lang.ClassCastException: [Ljava.lang.String; cannot be cast to java.lang.String. Поэтому я посмотрел на значения с помощью отладчика, и, конечно же, моя HashMap содержит строки, обернутые в массивы длины 1 вместо простых простых строк: даже жесткая моя HashMap четко определена с типами Integer-> String, и присвоение String работает без явного приведение типов. Это меня действительно сбивает с толку. Я предполагаю, что это имеет отношение к материалам Atlassian, автоматически десериализирующим POST-значения; в прошлом это уже стоило мне довольно много головной боли, так как нет надлежащей документации, а волшебное преобразование фона имеет довольно много причуд. Что действительно меня сильно смущает, так это тот факт, что HashMap может внезапно хранить значения другого типа, чем определено, я бы не подумал, что это возможно, если Java уделяет такое внимание безопасности типов. Есть ли какое-то отражение foo, которое может это сделать, о котором я не знаю? Или я неправильно понимаю природу HashMaps? Кто-нибудь когда-нибудь испытывал нечто подобное? У меня нет опыта программирования на Java.
Для тех, кто борется с формами Atlassian xwork / velocity, очевидно, синтаксис field[1] для карт не работает. Возможно, field.1 сработает, точечный синтаксис отлично работает для вложенных объектов (если вы используете @ParameterSafe в своих классах). Массивы работают в виде <input name = "test" value = "A"><input name = "test" value = "B">вместо<input name = "test[]" value = "A"><input name = "test[]" value = "B">.




Если вы создаете хэш-карту как HashMap<Integer, String>(), но сохраняете ее как HashMap, действительно можно хранить там другие типы.
Например:
HashMap map = new HashMap<Integer, String>();
map.put(1, new String[]{"1", "2"});
System.out.println(map.get(1));
Этот код выполняется без ошибок.
Итак, я думаю, что происходит то, что вы храните его как ссылку на HashMap, которая рассматривается как HashMap<Object, Object>, и поскольку во время выполнения нет информации о фактических универсальных типах, вы можете добавлять объекты других типов в эту коллекцию.
Но если у вас есть другая ссылка на ту же карту с HashMap<Integer, String>, тогда, когда вы вызываете, например, get(), он не сработает, за исключением описанного вами:
HashMap map = new HashMap<Integer, String>();
map.put(1, new String[]{"1", "2"});
System.out.println(map.get(1));
System.out.println("got here");
HashMap<Integer, String> otherRef = (HashMap<Integer, String>) map;
System.out.println(otherRef.get(1)); //<-ClassCastException exception here