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的作者]