如何获得具有 java 反射的列表的通用 class?

How to get the generic class of a list with java reflectioin?

我有一个局部变量 List 或其他一些 List 我想得到这个列表变量的泛型 class。

该变量不是成员变量,所以不要使用 Field 来获取泛型 class。

方法应该是

public Class<?> getGenericClass(List<E> list){

      //somehow to return Class E

}

编辑: 我尝试了@Radiodef 的解决方案,但出现异常

java.lang.ClassCastException: sun.reflect.generics.reflectiveObjects.TypeVariableImpl cannot be cast to java.lang.Class

在第 Class genericClazz = (Class) pt .getActualTypeArguments()[0].

public static void main(final String[] args) throws IOException {
    final List<String> list = new ArrayList<String>();
    list.add("aaa");
    final Type type = list.getClass().getGenericSuperclass();
    if (type instanceof ParameterizedType) {
        final ParameterizedType pt = (ParameterizedType) type;
        final Class<?> genericClazz = (Class<?>) pt
                .getActualTypeArguments()[0];
        System.out.println(genericClazz.getName());
    }
}

编译器将 List 视为 List(没有类型信息),因此无法通过反射获取通用类型。

你能做什么:

  • 扫描列表的每个元素并找到最具体的公共超级class
  • 扫描列表的每个元素并找到所有公共接口

这两种方法都会遍历列表元素,然后反射性地扫描 class 层次结构。

这是唯一可以做到的方法:

import java.lang.reflect.*;

static <E> Class<E> getClassE(List<E> list) {
    Class<?> listClass = list.getClass();

    Type gSuper = listClass.getGenericSuperclass();
    if(!(gSuper instanceof ParameterizedType))
        throw new IllegalArgumentException();

    ParameterizedType pType = (ParameterizedType)gSuper;

    Type tArg = pType.getActualTypeArguments()[0];
    if(!(tArg instanceof Class<?>))
        throw new IllegalArgumentException();

    @SuppressWarnings("unchecked")
    final Class<E> classE = (Class<E>)tArg;
    return classE;
}

但是,您传入的 List 必须 是具有具体类型的子类。

例如如果你打电话

... = getClassE( new ArrayList<String>() );

它会抛出:因为泛型是 erased,所以 Class<E> 通常在 运行 时不可用。

通常在使用这种模式时,你会使用一个匿名子类,例如:

//                                       vv
... = getClassE( new ArrayList<String>() {} );

不过你也可以

class StringList extends ArrayList<String> {}
... = getClassE( new StringList() );

当我们像这样创建一个子类时,Class<E> 会被存储,我们可以通过我答案第一部分中的反射来检索它。

另见:http://gafter.blogspot.com/2006/12/super-type-tokens.html.

Ideone 的实际例子:http://ideone.com/O2Gztj.