泛型 - 获取引用类型

时间:2015-01-13 07:48:24

标签: java generics reflection arraylist

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

我有一个POJO课程

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)

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

2 个答案:

答案 0 :(得分:2)

我不认为你想要实现的目标是可能的。但是,对代码稍作修改可以解决问题:

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

答案 1 :(得分:1)

方法getGenericType()的返回类型为Type,其中包括ClassParameterizedType。对我来说,如果在没有参数化类型的字段上调用它,它将不会返回ParameterizedType。在这种情况下似乎返回Classjavadoc对此有点不确定。

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

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