Java泛型反射:子类的通用字段类型

时间:2010-08-10 15:16:42

标签: java generics reflection

给出两个这样的类:

class Example1<A,B> {

  public Map<A,B> someMap = new HashMap<A,B>();

}

class Example2 extends Example1<URL, URL> {


}

有没有办法使用反射我可以确定Example2的Map的组件类型?

我知道我能做到:

ParameterizedType t = (ParameterizedType) Example2.class.getFields()[0].getGenericType();

但是从那里开始,我似乎无法弄清楚这两个组件是URL。

有没有人有任何想法?

4 个答案:

答案 0 :(得分:7)

达隆并不完全正确。以下将打印出您想要的内容:

ParameterizedType superClass = (ParameterizedType) Example2.class.getGenericSuperclass();
System.out.println(superClass.getActualTypeArguments()[0]);
System.out.println(superClass.getActualTypeArguments()[1]);

打印出来:

class java.net.URL
class java.net.URL

答案 1 :(得分:1)

由于Java泛型是通过“擦除”实现的,因此在运行时通过反射无法获得此信息。

编辑:似乎我错过了一些问题的细节。在这种特殊情况下,可以获得类型信息。

答案 2 :(得分:1)

您的答案不太正确 - 您将返回Class的泛型类型,而不是“someMap”字段类型。

当然,在给定someMap的参数的示例中,它们与类的参数相同,但是如果someMap被定义为,并且地图类型不是两个URL,则有一个关于如何将泛型类型的参数映射到字段的。

一个更好的例子可能是:

class Example1<A,B> {

  public Map<B,A> someMap = new HashMap<B,A>();

}

class Example2 extends Example1<URL, String> {


}

在这种情况下,回答问题:Example2中的某些Map的类型是什么?答案应该是:

java.lang.String中 的java.net.URL

但是,我仍然无法弄清楚如何做到这一点。

答案 3 :(得分:1)

Java反射API没有直接提供所需内容的方法,但它确实公开了使用Field.getGenericType()和{{计算所需的所有基本信息。 1}}。 但是,对于任何类层次结构和字段类型来说,解决这个问题并非易事。

要执行此操作计算,您可以使用gentyref库。 在您的示例中,您可以获取someMap变量的类型,如下所示:

Class.getGenericSuperclass()

如果有足够的信息(在Example2中,它是),someMapType将是ParameterizedType。然后你可以得到键的类型和值:

Type someMapType = GenericTypeReflector.getExactFieldType(
   Example2.class.getField("someMap"),
   Example2.class);

这将是包含((ParameterizedType)someMapType).getActualTypeArguments(); 两次的数组。请注意,它也可以包含除类之外的其他内容(例如,另一个ParameterizedType)。因此,如果你想用这种类型做一些非平凡的事情(例如,看看它是否是另一种类型的超类型),GenericTypeReflector中的其他方法也可以派上用场......

[我是gentyref的作者]