【问题标题】:How to get the generic class of a list with java reflectioin?java - 如何使用java反射获取列表的泛型类?
【发布时间】:2015-04-08 10:55:22
【问题描述】:

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

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

方法应该是

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

      //somehow to return Class E

}

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

java.lang.ClassCastException: sun.reflect.generics.reflectiveObjects.TypeVariableImpl 无法转换为 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());
    }
}

【问题讨论】:

  • 你试过了吗?

标签: java list generics reflection field


【解决方案1】:

这是唯一可行的方法:

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&lt;E&gt; 在运行时通常不可用。

通常在使用此模式时,您会使用匿名子类,例如:

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

但你也可以这样做

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

当我们创建这样的子类时,Class&lt;E&gt; 被存储,我们可以通过我的答案第一部分中的反射来检索它。

另请参阅:http://gafter.blogspot.com/2006/12/super-type-tokens.html

还有 Ideone 示例:http://ideone.com/O2Gztj

【讨论】:

  • 我得到 java.lang.ClassCastException:sun.reflect.generics.reflectiveObjects.TypeVariableImpl 不能在 pType.getActualTypeArguments()[0] 处转换为 java.lang.Class;
  • 这很有趣。你完全复制了吗? (我所有的演员都被保护了,所以如果有问题你应该得到IllegalArgumentException,而不是ClassCastException。)你传递给它什么?
  • 请看我新的 cmets
  • 再次阅读我的答案的第二部分。如果您要使用此代码,无论您在哪里使用 new ArrayList&lt;MyType&gt;(),您都需要将其更改为 new ArrayList&lt;MyType&gt;() {} 或创建 ArrayList 的子类,如 class MyList extends ArrayList&lt;MyType&gt; {}
【解决方案2】:

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

你可以做什么:

  • 扫描列表的每个元素并找到最具体的常见超类
  • 扫描列表中的每个元素并找到所有常用接口

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-02
    • 1970-01-01
    • 2015-04-18
    • 1970-01-01
    • 2017-11-20
    • 1970-01-01
    相关资源
    最近更新 更多