Как определить тип в универсальном методе в Java? - PullRequest
1 голос
/ 26 марта 2012

Мне нужен метод, который извлекает данные из JSON-объекта, проанализированного ранее, как правильный тип. JSONObject (rawdata) расширяет Map, поэтому он выглядит следующим образом:

private <Type> Type getValue(String key, Type def)
{
    if (!rawdata.containsKey(key)) return def;
    if (!(rawdata.get(key) instanceof Type)) return def;
    return (Type) rawdata.get(key);
}

instanceof, очевидно, генерирует ошибку времени компиляции. Параметр def является значением по умолчанию, которое возвращается, если ключ недоступен или имеет неправильный тип. Но def также может быть нулевым, поэтому def.getClass() не работает.

Любые идеи, как я могу проверить содержимое записи карты для правильного типа?

Ответы [ 4 ]

7 голосов
/ 26 марта 2012

Из-за стирания типа единственный способ справиться со случаем, когда значение по умолчанию может быть нулевым, состоит в том, чтобы метод требовал дополнительного параметра типа Class - что, как правило, лучше, так как позволяет значению по умолчанию быть подкласс требуемого типа.

2 голосов
/ 26 марта 2012

Вам просто нужно проверить наличие нулей (ноль будет учитываться как любой тип, если это нежелательное поведение, вам также нужно будет передать требуемый класс).

private <T> T getValue(String key, T def)
{
    if (!rawdata.containsKey(key)) return def;

    Object value = rawdata.get(key);

    if (def == null) return (T) value; 
    // note that the above is inherently unsafe as we cannot 
    // guarantee that value is of type T

    // this if statement is the same as "value instanceOf Type"
    // is type safe, but not null safe
    if (def.getClass().isAssignableFrom(value.getClass())) {
        return (T) value;
    } else {
        return def;
    }
}

Подпись более безопасного метода будет:

private <T> T getValue(String key, T defaultValue, Class<T> defaultClass)

Таким образом, мы можем безопасно проверять совпадение типов, даже если значение по умолчанию равно нулю.

1 голос
/ 26 марта 2012

Лучше всего принять объект типа Class для типа возврата в случае, если значение по умолчанию не указано. Вы можете просто перегрузить функцию как:

private <T> T getValue(String key, Type defaultValue);

private <T> T getValue(String key, Class<T> type);
0 голосов
/ 31 марта 2012

Или вы можете использовать шаблон Гетерогенный контейнер Typesafe (THC) из книги "Effective Java Second Edition" Джошуа Блока.

По сути, при вставке сохраняйте класс предмета на карте. При получении вы будете знать, что тип тот же.

Map<Class, Map<String, Object>> rawData = ...
...