【问题标题】:How to get Class<T> from List<T>如何从 List<T> 中获取 Class<T>
【发布时间】:2016-05-23 08:43:04
【问题描述】:

不得不问这个问题我觉得很傻,但我不明白为什么下面的 Java 代码不能编译:

void <T> doSomething(List<T> items) {
    Class<? extends T> clazz = items.get(0).getClass();
    ...
}

来自 Java 文档:

实际结果类型是 Class 其中 |X|是个 擦除 getClass 所在的表达式的静态类型 叫。例如,此代码片段中不需要强制转换:

数字 n = 0;类 c = n.getClass();

编辑:

  1. 找到this nice explanation 了解删除静态类型的含义。

  2. 有一种方法可以使用子类来保存泛型类型信息,称为super type token。一个现已删除的答案很有帮助地指出,Guava 库有一个 convenient utility 来利用它。

  3. 这里有一个great article,关于反射性地提取泛型类型和一个不错的库,称为GenTyRef,简化了它

  4. 我派生了 GenTyRef 以添加对使用 AnnotatedTypes 的支持(在 Java 8 中引入)。它被称为GeantyRef(它位于 Maven 中心)

【问题讨论】:

  • 我认为这是重复的或至少是矩阵错误,因为我感觉我之前在 SE 上看到过这个问题
  • 如果TList&lt;String&gt; 怎么办?没有Class&lt;List&lt;String&gt;&gt;
  • Java 中没有auto

标签: java generics reflection


【解决方案1】:

items.get(0)的静态类型的擦除是Object(因为T在编译期间被擦除)。

因此items.get(0).getClass() 返回Class&lt;? extends Object&gt;,而不是Class&lt;? extends T&gt;,这解释了您尝试分配失败的原因。

这将通过编译:

Class<? extends Object> clazz = items.get(0).getClass();

如果您希望该方法知道泛型参数的Class,您可以将其作为附加参数传递。

void doSomething(List<T> items, Class<T> clazz) {

}

【讨论】:

  • Class&lt;? extends Object&gt; 是多余的,Class&lt;?&gt; 更简洁
  • @user140547 我使用的是 Javadoc (Class&lt;? extends |X|&gt;) 的语言。
  • @Eran Class&lt;? extends T&gt; clazz 不安全 - 您可以致电 doSomething(Arrays.&lt;Number&gt;asList(Double.valueOf(0)), Integer.class)。你需要使用&lt;? super T&gt;,不是吗?
  • 嗯,这并没有解释为什么结果带有“表达式的静态类型的擦除”,而不仅仅是“表达式的静态类型”……
  • @newacct:现在那个也许应该包含在答案中……
【解决方案2】:

首先,您需要将 T 定义为方法的类型参数:&lt;T&gt; void doSomething。然后你需要投到Class&lt;? extends T&gt;。所以你可以这样组合:

<T> void doSomething(List<T> items) {
    Class<? extends T> clazz = (Class<? extends T>) items.get(0).getClass();
    ...
}

【讨论】:

  • 奇怪的是擦除迫使我们再次投射。
  • 缺少的 是一个错字。投射显然会起作用,但我需要解释为什么需要它。
猜你喜欢
  • 2017-03-07
  • 1970-01-01
  • 1970-01-01
  • 2022-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多