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

时间:2012-07-19 14:31:09

标签: java generics reflection

  

可能重复:
  get type of a generic parameter in java with reflection
  Get generic type of class at runtime

假设我有这样一个类:

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

有没有办法确定运行时“T”和“M”是什么? e.g。

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

谢谢!

3 个答案:

答案 0 :(得分:4)

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

也就是说,有一些时髦的解决方法。您可以明确查找该对的组件,并询问其类型。你可以使用匿名内部类的酷技巧,例如Guava的TypeToken使用 - 您无法在运行时确定new Foo<String, Integer>()的类型,但可以确定new Foo<String, Integer>() {}的类型在运行时 - 注意匿名内部类, 保留为其超类指定的泛型参数,即Foo。 (披露:我向Guava捐款。)

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

所有这一切,唯一能满足这种需求的通用解决方案是明确传递Class元数据。

答案 1 :(得分:1)

运行时通用信息将被删除。一旦您的类编译,所有通用类型信息将erased并替换为:

  

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

答案 2 :(得分:0)

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

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

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

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