Java Generics Reflection:子类的通用字段类型

给出两个这样的类:

class Example1 { public Map someMap = new HashMap(); } class Example2 extends Example1 { } 

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

我知道我能做到:

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

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

有没有人有任何想法?

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

 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 

由于Javagenerics是通过“擦除”实现的,因此在运行时通过reflection无法获得此信息。

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

你的答案不太正确 – 你返回的是类的generics类型,而不是“someMap”字段类型。

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

一个更好的例子可能是:

 class Example1 { public Map someMap = new HashMap(); } class Example2 extends Example1 { } 

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

java.lang.String java.net.URL

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

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

为此,您可以使用gentyref库。 在您的示例中,您可以像这样获取someMap变量的类型:

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

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

 ((ParameterizedType)someMapType).getActualTypeArguments(); 

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

[我是gentyref的作者]