【问题标题】:Get a Class<Foo<T>> at runtime given generic type inputs给定泛型类型输入,在运行时获取 Class<Foo<T>>
【发布时间】:2014-09-24 01:48:30
【问题描述】:

我知道已经有很多关于类似问题的问题,但我还没有找到直接解决这个问题的问题。

这是我尝试实现的代码框架:

class MyObj<T> {
    // Internals are unimportant ...
}

private <T> void foo(T arg) {
    Class<MyObj<T>> clazz = // What do I write here?

    // Here is one thing that works, but is quite ugly:
    @SuppressWarnings("unchecked")
    clazz = (Class<MyObj<T>>)(new MyObj<T>().getClass())

    // ...

    // Later, clazz is passed to a constructor of some other class
    OtherClass<MyObj<T>> foo = new OtherClass<>(clazz);
}

问题 1: 有人对如何填充 clazz 有更好的建议吗?理想情况下,它会避免调用new

问题 2: 鉴于上述丑陋(但有效)的代码,在任何情况下它可能会中断吗?我不喜欢@SuppressWarnings,担心我可能隐藏的问题。

【问题讨论】:

  • 由于擦除,Class&lt;MyObj&lt;T&gt;&gt; 将只绑定到任何Object。改用Class&lt;?&gt; 可能会更好;这样,您也可以通过arg.getClass()arg 中提取课程信息。
  • 你想用clazz做什么?
  • @TedHopp clazz,在我的例子中,被传递到另一个泛型层。它将被传递给另一个类构造函数,该构造函数在内部使用该 Class 来实例化等。我将更新问题以反映这一点。
  • @Makoto:如果我理解正确,我不能使用arg.getClass(),因为这会给我一个Class&lt;T&gt;,而我想要一个Class&lt;MyObj&lt;T&gt;&gt;

标签: java generics


【解决方案1】:

为了避免实例化,你可以这样写:

Class<MyObj<T>> clazz = (Class) MyObj.class;

由于擦除,Class 存在单个 Class 实例,不管它可能有什么类型参数,所以虽然这很难看,但它是安全的。

【讨论】:

  • 谢谢,这行得通!我还在 cmets 中链接的另一个问题中看到了以下变体:clazz = (Class&lt;MyObj&lt;T&gt;&gt;)(Class&lt;?&gt;)MyObj.class。有趣的是,在那种情况下需要双重演员......
  • @jwd:假设您想从Integer 转换为String。它们是不兼容的类型,所以你不能写String s = (String) i:编译器可以告诉你那不行。您必须向上转换为Object,然后然后向下转换为StringString s = (String) (Object) i。 (然后你会得到一个ClassCastException,当然。)就类型系统而言,这是一回事;您需要将Class&lt;MyObj&gt; 向上转换为ClassClass&lt;?&gt;,以欺骗编译器让您向下转换为Class&lt;MyObj&lt;T&gt;&gt;[继续]
  • [continued] 我的版本只需要一个显式转换——向上转换为Class,而不向下转换为Class&lt;MyObj&lt;T&gt;&gt;——的原因是原始类型在 Java 中具有特殊处理,并允许您隐式(且不安全地)转换为任何相应的参数化类型。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多