HashMap<Integer, String> ClassCastException [Решено]

274
22 февраля 2017, 21:03

Не понял, в чём проблема?

Консоль:

Caused by: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer

Я же ключи ставлю, а ключи это Integer. Зачем он их пытается кастовать в String?!

        private HashMap<Integer, String> RanksList = new HashMap<>();
        if (this.getConfig().contains("PlayerRank")) {
        this.RanksList = (HashMap) this.getConfig().getConfigurationSection("PlayerRank").getValues(false);
    } else {
        this.getConfig().set("PlayerRank.100", "\u00a7a\u00a7lНовичок\u00a7r");
        this.getConfig().set("PlayerRank.500", "\u00a7e\u00a7lОпытный\u00a7r");
        this.getConfig().set("PlayerRank.1500", "\u00a71\u00a7lВетеран\u00a7r");
        this.getConfig().set("PlayerRank.3000", "\u00a75\u00a7lМастер\u00a7r");
        this.getConfig().set("PlayerRank.4500", "\u00a7c\u00a7lЛегенда Зоны\u00a7r");
        this.RanksList = (HashMap) this.getConfig().getConfigurationSection("PlayerRank").getValues(false);
    }

Это часть моего кода из загрузки конфига плагина на сервер майнкрафта. Bukkit.

Answer 1

Предположим, что метод getValues возвращает Map<String, String>:

private static Map<String, String> getValues()
{
    HashMap<String, String> map = new HashMap<>();
    map.put("abc", "def");
    return map;
}

Если некорректно с ним работать (с использованием raw-type вместо generics), то вполне возможна такая ситуация:

public static void main(String[] args)
{
    HashMap<Integer, String> ranksList = (HashMap)getValues();
    for (int i : ranksList.keySet())
    {
        System.out.println("Key: " + i);
    }
}

Которая приведёт к

java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer

Так как на самом деле в хэш-таблице в качестве ключей участвуют String, а сделать Integer из String простым приведением типа нельзя.

Если бы код был такой:

HashMap<Integer, String> ranksList = (HashMap<Integer, String>)getValues();

То была бы ошибка компиляции:

java.lang.RuntimeException: Uncompilable source code - incompatible types: java.util.Map<java.lang.String,java.lang.String> cannot be converted to java.util.HashMap<java.lang.Integer,java.lang.String>

Можно предположить, что метод getValues возвращает просто Map, из-за чего уже и

 HashMap<Integer, String> ranksList = (HashMap<Integer, String>)getValues();

не спасёт ситуацию (код скомпилируется, но ClassCastException, конечно, никуда не денется), но это уже будет вина разработчиков метода getValues.

И, судя по новому скриншоту

Метод getValues возвращает Map<String, Object>, который содержит в качестве ключей String и который не стоит пытаться кастовать к Map<Integer, String>, потому что ни тип ключей не совпадает, ни тип значений.

Если нельзя изменить возвращаемый getValues тип, то можно создать Map<Integer, String> на базе Map<String, Object>:

HashMap<Integer, String> ranksList = new HashMap<>();
Map<String, Object> map = getValues();
for (String key : map.keySet())
{
    ranksList.put(Integer.parseInt(key), String.valueOf(map.get(key)));
}

Или с использованием Java 8:

HashMap<Integer, String> ranksList = new HashMap<>();
Map<String, Object> map = getValues();
map.forEach((key, value) -> ranksList.put(Integer.parseInt(key), String.valueOf(value)));

Также не стоит забывать, что если какой-то из ключей в map не подходит под формат, принимаемый методом Integer.parseInt, то будет проброшено NumberFormatException.

Answer 2

Проблема решена. Всем спасибо. Поправьте меня, если где то сделал лишние)

    if (this.getConfig().contains("PlayerRank")) {
        for (Map.Entry<String, Object> entry : this.getConfig().getConfigurationSection("PlayerRank").getValues(false).entrySet()) {
            this.RanksList.put(Integer.parseInt(entry.getKey()), String.valueOf(entry.getValue()));
        }
    } else {
        this.getConfig().set("PlayerRank.100", "\u00a7a\u00a7lНовичок\u00a7r");
        this.getConfig().set("PlayerRank.500", "\u00a7e\u00a7lОпытный\u00a7r");
        this.getConfig().set("PlayerRank.1500", "\u00a71\u00a7lВетеран\u00a7r");
        this.getConfig().set("PlayerRank.3000", "\u00a75\u00a7lМастер\u00a7r");
        this.getConfig().set("PlayerRank.4500", "\u00a7c\u00a7lЛегенда Зоны\u00a7r");
        for (Map.Entry<String, Object> entry : this.getConfig().getConfigurationSection("PlayerRank").getValues(false).entrySet()) {
            this.RanksList.put(Integer.parseInt(entry.getKey()), String.valueOf(entry.getValue()));
        }
    }
READ ALSO
Некорректная отправка файла через socket

Некорректная отправка файла через socket

Пытаюсь отправлять любой файл по TCP с моего клиента (на мобильном устройстве) на консольный сервер (на компьютере)Подключение, отправка, получение,...

224
Конвертируем метод в kotlin

Конвертируем метод в kotlin

Пытаюсь преобразовать данный метод в котлин

310
Как открыть emoji keyboard

Как открыть emoji keyboard

Такой вопрос, как открыть Emojii keyboard программно? Например, при нажатии на кнопку, сразу должна открываться часть клавиатуры с emoji

234
Андроид, как описать лого в NavigationDrawer

Андроид, как описать лого в NavigationDrawer

Я хочу использовать эту библиотеку, похоже что пользоваться ей очень удобно, но я не понимаю как поместить свой логотип в верхнюю часть Drawer'a...

309