Java получает общий тип коллекции
Мой проект включает отражение, и в настоящее время я обрабатываю общие типы. Мне удалось получить общий тип из списка (java.util.List) с помощью:
if(originalField.getGenericType() instanceof ParameterizedType){
ParameterizedType pt = (ParameterizedType) originalField.getGenericType();
Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0];
}
У меня также есть Collection<String>
и получается, что коллекция не может быть приведена к ParameterizedType.
У кого-то есть идея, как получить String (или любой другой тип, который будет) из коллекции?
Я читал о стирании Java, поэтому я знаю об этом, но, получив общий список из списка, я подумал, что, может быть, кто-то знает еще один "трюк".
Благодарю.
EDITED: Я повторяю все поля класса:
for (Field originalField : someClass.getDeclaredFields())
И затем, когда я столкнулся с каким-то полем List<String>
, с приведенным выше кодом я получаю String
в качестве переменной subClass.
Ответы
Ответ 1
Твой подход прекрасен. Он должен работать как для List<String>
и для Collection<String>
. Например, см. Пример кода:
public class Demo {
List<String> list = new ArrayList<>();
Collection<String> coll = new ArrayList<>();
public static void main(String args[]){
Class<Demo> clazz = Demo.class;
Field[] fields = clazz.getDeclaredFields();
for (Field field: fields) {
Type type = field.getGenericType();
if (type instanceof ParameterizedType) {
ParameterizedType pType = (ParameterizedType)type;
Type[] arr = pType.getActualTypeArguments();
for (Type tp: arr) {
Class<?> clzz = (Class<?>)tp;
System.out.println(clzz.getName());
}
}
}
}
}
это печатает:
java.lang.String
java.lang.String
Ответ 2
Насколько я знаю, Java полностью стирает тип, поэтому скомпилированный код не имеет следов значения, которое вы назначили параметрам. Все параметрические типы переводятся на конкретные типы, с типом отливок и т.д.
В коде, который я видел до сих пор, когда класс должен знать значение своего родового типа, он заставляет объект этого типа (или класса) передаваться в качестве параметра. Что-то вроде:
class A<T> {
private final Class<T> parameterType;
public A(Class<T> parCls) {
parameterType = parCls;
}
public A(T tObj) {
parameterType = tObj.getClass();
}
}
Ответ 3
Вам нужно будет разрешить параметр ParameterizedType, используя любой тип, на котором он был определен. Например, используя TypeTools:
class Foo<T> {
public T bar;
}
class StringFoo extends Foo<String> {}
Type barType = Foo.class.getDeclaredField("bar").getGenericType();
Class<?> t = TypeResolver.resolveRawClass(barType, StringFoo.class);
assert t == String.class;
Здесь значение T
было определено в StringFoo, поэтому мы можем использовать TypeResolver
для разрешения исходного класса для нашего типа поля с помощью StringFoo