0

可能重复:
在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?

谢谢!

4

3 回答 3

4

不,没有。这几乎就是类型擦除的定义。

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

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

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

于 2012-07-19T14:32:36.110 回答
1

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

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

于 2012-07-19T14:33:56.937 回答
0

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

因此,在您的情况下,如果 foo1 和 foo2 是某个类中的实例变量:

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

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

于 2012-07-19T14:45:33.673 回答