给出两个这样的类:
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。
有没有人有任何想法?
答案 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的作者]