泛型 - 获取引用类型

Generics - Get the reference type

我在获取列表类型时遇到问题。问题是在声明时我没有指定类型。我只在 运行 时间设置它。

我有一个 POJO class

public class MyObject<T> {

    private String name;
    private List<T> list;

//getter and setter
}

我已关注 this SO question 并尝试了以下代码

public class ListType {

    public static void main(String[] args) throws NoSuchFieldException, SecurityException {
        ListType listType = new ListType();
    List<Integer> listInt = new ArrayList<Integer>();
    MyObject<Integer> myObjectInt = new MyObject<Integer>();
    myObjectInt.setList(listInt);
    listType.initialize(myObjectInt);

    MyObject<String> myObjectStr = new MyObject<String>();
    List<String> listStr = new ArrayList<String>();
    myObjectStr.setList(listStr);
    listType.initialize(myObjectStr);
    }

    private void initialize(MyObject myObject) throws NoSuchFieldException, SecurityException {
        List list = myObject.getList();
        ListType listType = new ListType();
        listType.getListType(list);
    }

    private void getListType(List list) throws NoSuchFieldException, SecurityException {
        Field stringListField = MyObject.class.getDeclaredField("list");
        ParameterizedType stringListType = (ParameterizedType) stringListField.getGenericType();
        Class<?> stringListClass = (Class<?>) stringListType.getActualTypeArguments()[0];
        System.out.println(stringListClass);
    }

}

然后我得到以下异常

Exception in thread "main" java.lang.ClassCastException: sun.reflect.generics.reflectiveObjects.TypeVariableImpl cannot be cast to java.lang.Class
    at com.sample.listtype.ListType.getListType(ListType.java:35)
    at com.sample.listtype.ListType.initialize(ListType.java:27)
    at com.sample.listtype.ListType.main(ListType.java:15)

如果我设置在 运行 时间,如何获取类型?

这个方法getGenericType() has the return type Type which, amongst others, can be Class or ParameterizedType. It makes sense to me that it wouldn't return ParameterizedType if invoked on a field which has no parameterized type. It seems to return Class in this case. The javadoc有点不确定。

关于如何在运行时获取实际类型的问题:通用类型信息在运行时被删除。它仅用于确保编译时的类型安全。当你将一个实际类型ArrayList<Integer>的对象赋值给一个静态类型List的变量时,你无法在运行时得到实际对象的泛型类型。您可以做的是检查列表中包含的对象的类型:

Class<?> foo = list.get(0).getClass();

我不认为你想要实现的是可能的。然而,对代码稍作改动就可以解决问题:

public class MyObject {
    private List<?> list;
    private Class<?> type;

    public <T> void setList(List<T> list, Class<T> c) {
        this.list = list;
        this.type = c;
    }

    public List<?> getList() {
        return list;
    }

    public Class<?> getType() {
        return type;
    }
}

示例代码:

public static void main(String[] args) throws NoSuchFieldException,
        SecurityException {
    List<Integer> list = new ArrayList<Integer>();
    MyObject myObject = new MyObject();
    myObject.setList(list, Integer.class);

    System.out.println(myObject.getType());
}

输出:

class java.lang.Integer