Как заменить TypeToken из Guava на Gson (особенно при использовании универсальных типов) - PullRequest
0 голосов
/ 30 октября 2018

В настоящее время я пытаюсь реорганизовать проект, чтобы избежать использования guava в качестве зависимости. Я использовал его в основном для функций, связанных с отражением, но в большинстве случаев я мог найти альтернативу.

Однако остался один случай, который я пока не могу исправить: Я пытаюсь получить класс универсального параметра текущего класса.

Работает нормально, используя Guava, поскольку тип, возвращаемый TokenType, может быть приведен к классу.

Гуава:

(Class<I>) new com.google.common.reflect.TypeToken<I>(getClass()) {}.getType();

Я попытался заменить этот вызов, используя вместо этого TypeToken из Gson, но, по-видимому, информация о I потеряна, и в результате этого вызова получается TypeVariable, который сохраняется как класс после выполнения:

Gson:

(Class<I>) new com.google.gson.reflect.TypeToken<I>() {}.getType();

Насколько я могу судить, параметр getClass () является подсказкой, почему контекст не сохраняется. Когда я использую Guava с той же подписью:

(Class<I>) new com.google.gson.reflect.TypeToken<I>() {}.getType();

Я получаю это сообщение об ошибке:

java.lang.IllegalStateException: Невозможно создать TypeToken для переменной типа. Вы, вероятно, хотели вызвать новый TypeToken (getClass ()), который может разрешить переменную типа для вас. Если вам нужно создать TypeToken переменной типа, используйте взамен TypeToken.of ().

Я вижу Gson также в качестве (защищенного пакета) конструктора, использующего Type в качестве аргумента.

Есть ли способ получить класс универсального параметра, используя только Gson?

Редактировать # 1:

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

Гуава может быть приведена к Class<I>, а Гсон - нет. Я еще не уверен, какая базовая реализация для Guava, но Gson использует TypeVariable.

На данный момент я нашел обходной путь для использования двух данных, которые использует Гуава (тип + текущий класс), путем объединения результата Gson TypeToken (тип) с этим методом, который использует текущий класс в качестве контекста:

public static Type getActualType(Class context, Type parameterizedType) {
    if (parameterizedType instanceof TypeVariableImpl) {
        TypeVariable[] genericParameters = context.getSuperclass().getTypeParameters();
        Type[] implementations = ((ParameterizedTypeImpl) context.getGenericSuperclass()).getActualTypeArguments();
        for (int i = 0; i < genericParameters.length; i++) {
            if (genericParameters[i].getName().equals(((TypeVariableImpl) parameterizedType).getName())) {
                return implementations[i];
            }
        }
    }
    return parameterizedType;
}

(эта реализация взята из проекта buremba / netty-rest )

Это позволяет мне получить ожидаемый класс, вызвав:

(Class<I>) getActualType(getClass(), new com.google.gson.reflect.TypeToken<I>() {}.getType());

Это кажется немного трудоемким, я не уверен, что это лучший способ сделать это.

Примечание: вопрос также был поднят как проблема Github в проекте Gson

...