Вывод параметров java-обобщений во время выполнения с использованием отражения - PullRequest
4 голосов
/ 09 декабря 2010

У меня есть метод со следующей подписью:

// Converts a json string to a list of objects
// Assumption: json is an array, and all items in the list are of the same type
public <T> List<T> getListFromJson( String json, Class<T> itemType, List<T> defValue ) {
    final ArrayList<T> list = new ArrayList<T>();

    for( JsonElement e : parser.parse(json).getAsJsonArray())
        list.add( (T) (
                Number.class.isAssignableFrom(itemType) ? e.getAsNumber() :
                Boolean.class.isAssignableFrom(itemType) ? e.getAsBoolean() :
                Character.class.isAssignableFrom(itemType) ? e.getAsCharacter() :
                String.class.isAssignableFrom(itemType) ? e.getAsString() :
                JsonElement.class.isAssignableFrom(itemType) ? e :
                null
            )
        );

    return list;
}

Он читает строку json и преобразует ее в список объектов соответствующего типа, например. Целое число, строка и т. Д.

Есть ли надежный способ удалить аргумент Class<T> из метода, выведя его из параметра List<T>? Например. Есть ли способ изменить сигнатуру метода следующим образом без потери функциональности?

public <T> List<T> getListFromJson( String json, List<T> defValue ) {
    ...
}

Похоже, что решение потребует некоторых причудливых манипуляций с ParameterizedType. Я посмотрел на следующее, но либо я использую эти методы неправильно, либо они не выполняют то, что я ожидаю:

Ответы [ 2 ]

7 голосов
/ 09 декабря 2010

Из-за стирания типа вы определенно не можете "определить", что такое T - его даже не существует во время выполнения. Самое близкое, что вы могли бы получить, это проверить значения в defValue (если оно имеет значения) и получить класс элементов там.

Class<?> tType = defValue.get(0).getClass();

if (Boolean.class.isAssignableFrom(tType)) { //...  

Редактировать

Что касается вашего мышления об использовании отражения типа getTypeArguments() и т. Д. Они предоставляют данные только для объявленных типов, но не реальных типов. Так, например, если вы получили дескриптор объекта Method и назвали getTypeParameters(), вы просто получили бы массив, содержащий объект типа, представляющий T, а не фактический тип, который T представляет в некотором конкретном вызов времени выполнения.

1 голос
/ 09 декабря 2010

Единственный известный мне способ гарантировать доступ к типу во время выполнения - это сделать его параметром для конструктора объекта следующим образом:

class MyClass<T> {
    private final Class<T> clazz;
    public MyClass(Class<T> clazz) {
        this.clazz=clazz;
    }
}

Затем вам нужно будет передать класс, когда высоздать экземпляр объекта:

MyClass<String> object = new MyClass<String>(String.class);

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...