使用反射(或类似的东西)对泛型类型进行运行时确定



可能的重复项:
获取 Java 中泛型参数的类型(带反射
( 在运行时获取类的泛型类型

假设我有这样的类:

public class Foo<T, M> {
  Pair<T, M> bar;
}

有没有办法确定运行时的"T"和"M"是什么? 例如

Foo<String, Integer> foo1 = new Foo<String, Integer>();
Foo<Integer, Boolean> foo2 = new Foo<Integer, Boolean>();
// what happens next?

谢谢!

No. 没有。 这几乎就是类型擦除的定义。

也就是说,有一些时髦的解决方法。 您可以显式查找该对的组件,并询问它们的类型。 你可以对匿名内部类使用很酷的技巧,例如 Guava 的 TypeToken 使用——你不能在运行时确定new Foo<String, Integer>()的类型,但你可以在运行时确定new Foo<String, Integer>() {}的类型——注意匿名内部类,它保留了为其超类指定的泛型参数,即 Foo 。 (披露:我为番石榴做出贡献。

通常,最好的解决方案是首先避免需要这些信息。 没有关于如何做到这一点的一般食谱,但通常是可能的。

综上所述,满足此需求的唯一通用解决方案是显式传递Class元数据。

运行时泛型信息将被擦除。一旦你的类编译,所有泛型类型信息将被擦除和替换:

泛型类型中的所有类型参数及其边界或 Object (如果类型参数是无边界的(

实际上,java.lang.reflect.Field保留了泛型信息;因此,通过反射,您可以获得泛型信息,但仅适用于类/实例变量(不是方法返回类型,也不是局部变量(。

所以在你的例子中,如果 foo1 和 foo2 是某个类中的实例变量:

class FooTest {
    Foo<String, Boolean> foo1;
}

然后FooTest.class.getDeclaredField("foo1").getGenericType()将返回一个ParameterizedType实例,您可以在其中检查getActualTypeArguments()

最新更新