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