我试图在运行时获取接口使用的泛型类型Class<?>
。
所以,如果我有以下
public class A<T> implements B<Z> {}
public interface B<T> extends C<Z> {}
public interface C<T> {}
public class Z {}
A temp = new A<MyClass>();
我希望能够在给定实例Class<?>
的情况下获得B,C或D的第一个(或更晚的)通用的temp
。
现在我有这个,但它只适用于此实例的类直接实现的接口。无论此实例如何继承目标接口,我都想将其修改为工作。
/**
* Finds this instances implementation of the interfaceClass, and returns
* the associated generic type
*
* @param instance
* the instance to extract from
* @param interfaceClass
* The class this instance implements
* @param paramIndex
* Index of the generic class to get the class of
* @return The class of the generic type
* @throws ClassNotFoundException
*/
public static <T> Class<?> ParameterizedClass(final T instance, final Class<T> interfaceClass, final int paramIndex)
throws ClassNotFoundException {
final Type[] sooper = instance.getClass().getGenericInterfaces();
for (final Type t : sooper) {
if (!(t instanceof ParameterizedType)) {
continue;
}
final ParameterizedType type = ((ParameterizedType) t);
if (type.getRawType().getTypeName().equals(interfaceClass.getTypeName())) {
return Class.forName(type.getActualTypeArguments()[paramIndex].getTypeName());
}
}
return null;
}
使用我现在的代码和示例类,我得到以下结果
ParameterizedClass(new A<Integer>, B.class, 0); // returns Class<Z>
ParameterizedClass(new A<Integer>, C.class, 0); // returns null, but I want Class<Z>
这就是我直接实现的意思。我无法找到如何阅读继承的类。
答案 0 :(得分:0)
为了修复你的第二个调用以便它返回Class<Z>
我想你需要查询中间接口继承,在这种情况下B是要获得Class<Z>
。
你可以在第二个循环中使用这样的递归来做到这一点:
public static Class<?> parameterizedClass(final Class<?> root, final Class<?> target, final int paramIndex)
throws ClassNotFoundException {
final Type[] sooper = root.getGenericInterfaces();
for (final Type t : sooper) {
if (!(t instanceof ParameterizedType)) {
continue;
}
final ParameterizedType type = ((ParameterizedType) t);
if (type.getRawType().getTypeName().equals(target.getTypeName())) {
return Class.forName(type.getActualTypeArguments()[paramIndex].getTypeName());
}
}
for (final Class<?> parent : root.getInterfaces()) {
final Class<?> result = parameterizedClass(parent, target, paramIndex);
if (result != null) {
return result;
}
}
return null;
}
public static Class<?> parameterizedClass(final Object object, final Class<?> target, final int paramIndex)
throws ClassNotFoundException {
return parameterizedClass(object.getClass(), target, paramIndex);
}
答案 1 :(得分:0)
您可以使用我的实用工具类GenericUtil
,它具有以下方法
public static Type[] getGenericTypes(Type sourceType, Class<?> targetClass)
对于你的情况:
System.out.println(Arrays.toString(GenericUtil.getGenericTypes(A.class, B.class)));
System.out.println(Arrays.toString(GenericUtil.getGenericTypes(A.class, C.class)));
System.out.println(Arrays.toString(GenericUtil.getGenericTypes(B.class, C.class)));
System.out.println(Arrays.toString(GenericUtil.getGenericTypes(A.class, Z.class)));
将输出
[class xdean.stackoverflow.java.reflection.Q48193539$Z]
[class xdean.stackoverflow.java.reflection.Q48193539$Z]
[class xdean.stackoverflow.java.reflection.Q48193539$Z]
[]
您可以找到它的实施on github。它有详细的javadoc,它可以解决最复杂的情况。例如:
interface I1<A> {
}
interface I2<A, B> {
}
class C5<A> implements I1<I2<A, Object>> {
}
//return Type[]{I2<A, Object> (ParameterziedType)}
GenericUtil.getGenericTypes(C5.class, I1.class);
您可以在its test中找到更复杂的情况。
答案 2 :(得分:-1)
在理论上的java中,由于&#34; erasure&#34;这在运行时是不可能的。我经历过你可以做到但实际上只是为了第一级而且只有sun提供的类,所以不是在android中。在第二级,您只能找到您的标签(或其他)标签。