Ответ 1
Что делать, если у вас есть TypeToken<ArrayList<String>>
, и вы хотите получить Class<ArrayList>
(это необработанный тип). Если он вернет Class<T>
, тогда он вернет Class<ArrayList<String>>
, который вам не нужен Class<ArrayList>
.
Из эффективного Java Second Edition, пункт 28: "Не используйте типы подстановочных знаков в качестве типов возврата. Вместо того, чтобы предоставлять дополнительную гибкость для ваших пользователей, это заставит их использовать подстановочные типы в клиентском коде".
public final Class<? super T> getRawType()
Я только что столкнулся с универсальными подстановочными знаками, чтобы понять последнее предупреждение без предупреждения, которое у меня есть в куске кода, который я пишу, и я не понимаю, почему getRawType() возвращает тип подстановочного знака.
class Base<T>{}
class Child<T> extends Base<T>{}
public <C> void test (TypeToken<? extends Base<C>> token) {
Class<? extends Base<C>> rawType = (Class<? extends Base<C>>) token.getRawType();
}
Мне нужно отправить token.getRawType(), поскольку он возвращает
Class<? super ? extends Base<C>>
Что делать, если у вас есть TypeToken<ArrayList<String>>
, и вы хотите получить Class<ArrayList>
(это необработанный тип). Если он вернет Class<T>
, тогда он вернет Class<ArrayList<String>>
, который вам не нужен Class<ArrayList>
.
Если общий тип "токена" является классом типа (т.е. если S в
TypeToken<S>
- это класс java.lang.reflect.Type), то TypeToken.getRawType() возвращает необработанный тип, связанный с S. Он должен быть объектом класса, родителем S.
Смотрите исходный код TypeToken.
В некоторых случаях (например, с несколькими ограничениями) реализованная стратегия не будет работать, а тип raw - Ok: исходным типом будет Object.class
См. например MoreTypes:
public static Class<?> getRawType(Type type) {
...
} else if (type instanceof TypeVariable) {
// we could use the variable bounds, but that'll won't work if there are multiple.
// having a raw type that more general than necessary is okay
return Object.class;
} else {
...
}