【问题标题】:How to Get class of Elements that List Contains?如何获取列表包含的元素类?
【发布时间】:2011-12-29 08:58:08
【问题描述】:

我有一个这样的列表:

private List<T> myList = new ArrayList<T>();

我想获得 T 的 .class。我该怎么做?

我的意思是:

myList.getClass()

编辑: 我试过了:

 Field genericField = Wrapper.class.getDeclaredField("myList");
 ParameterizedType genericType = (ParameterizedType) genericField.getGenericType();
 Class<?> genericClass = (Class<?>) genericType.getActualTypeArguments()[0];

当我调试它时

通用类型

的值为:

java.util.List

所以我认为这肯定与那个问题不同:Get generic type of java.util.List 因为如果你用T 声明一个类并稍后在另一种方法中为T 分配一些东西,T 持有的类就会消失。

【问题讨论】:

  • @oers 我认为这个问题与您的建议不同。因为我使用T,它让一切变得不同。
  • @kamaci:从您的问题中不清楚 T 是否应该是具体类的占位符或封闭类的类型参数。在后一种情况下,说不可能的答案实际上是正确的。
  • @kamaci:啊,是的,它是不同的。 (最好提供更广泛的代码上下文。)不,没有办法做到这一点。
  • @MichaelBorgwardt 我试图解释它。 T 是这里的占位符,我实例化了我的类,所以 T 持有一些东西,但之后我认为它消失了。

标签: java class list


【解决方案1】:

你不能因为类型擦除。 泛型类型在运行时是未知的(它被“擦除”),它只在编译时使用。

这是 java 泛型和 c# 泛型之间的主要区别。

【讨论】:

    【解决方案2】:

    为什么你需要知道这个?也许这会满足你的需要

    // must be at least one element (and all elements are the same)
    Class elementType = myList.get(0).getClass(); 
    

    这样做的唯一方法是要么

    • 将类型存储在字段中并为此添加 getter 方法。

    喜欢

    private final Class<T> type;
    private final List<T> list = new ArrayList<T>();
    
    public Class<T> getType() { return type; }
    
    • 在实际字段上使用 getGenericType(),假设参数类型不是通用的。
    • 使用具有特定类型的子类。

    喜欢

    List list = new ArrayList<Integer>() { }; // create a specific sub-class
    final Class<? extends List> listClass = list.getClass();
    final ParameterizedType genericSuperclass = (ParameterizedType) listClass.getGenericSuperclass();
    Class elementType = (Class) genericSuperclass.getActualTypeArguments()[0];
    

    这样做的不利之处在于,您最终可能会创建大量匿名类,并可能与ArrayList.class != list.getClass() 然而list instanceof ArrayList 之类的东西混淆

    【讨论】:

    • 您可以创建一个包含该字段的类的匿名子类型。
    • @kamaci:第一个可以,但它需要您周围的类在其构造函数中采用Class&lt;T&gt; 参数。
    • 类型变量应该初始化?
    • @MichaelBorgwardt 由于我的限制,我不想将参数发送给 Wrapper 类的构造函数
    • 正如 MichaelBorgwardt 指出的,它必须在构造函数中设置。
    【解决方案3】:

    你不能。该信息在运行时不可用。如果您的列表不为空,您也许可以检查第一个元素的类。

    【讨论】:

    • 信息实际上在运行时可用,因为private关键字表明它是一个字段。
    • @MichaelBorgwardt,参数类型为T,您不能将其转换为Class
    【解决方案4】:

    这只有在您的示例中暗示的列表是一个字段并且类型参数是具体的而不是本身是封闭类的类型参数(在您的示例中似乎是这种情况)时才有可能,并且您只能通过反射获取该字段的声明类型参数:

    Field listField = Test.class.getDeclaredField("myList");
    ParameterizedType listType= (ParameterizedType) listField.getGenericType();
    Class contentClass = (Class) listType.getActualTypeArguments()[0];
    

    不确定这是否完全正确,但你明白了 - 它相当复杂,因为类型参数可以是有界的和通配符。

    【讨论】:

    • 如果上面的类型是T,这实际上不起作用。只有当参数类型是像List&lt;Integer&gt;这样的实际类时它才会起作用@
    • @PeterLawrey 你明白了。由于T,它不起作用
    猜你喜欢
    • 1970-01-01
    • 2022-12-01
    • 1970-01-01
    • 2013-09-17
    • 1970-01-01
    • 2021-10-28
    • 1970-01-01
    • 2021-02-22
    • 2022-11-01
    相关资源
    最近更新 更多