汎用インターフェースを実現する具体的なクラスの実装のタイプを取得します。
2404 ワード
プロジェクトにclassを書く時、Mapのような一般的なインターフェースを実現すればいいです。 以下のコードから実装された汎型インターフェースの具体的なタイプを取り出すことができます。
/**
* classToIntrospect genericIfc
* @param ownerClass class,
* @param classToIntrospect classToIntrospect
* @param genericIfc
* @return
*/
private static Class[] doResolveTypeArguments(Class ownerClass, Class classToIntrospect, Class genericIfc) {
while (classToIntrospect != null) {
if (genericIfc.isInterface()) {
// classToIntrospect
Type[] ifcs = classToIntrospect.getGenericInterfaces();
for (Type ifc : ifcs) {
Class[] results = doResolveTypeArguments(ownerClass, ifc, genericIfc);
if (results != null) {
return results;
}
}
} else {
//class.getGenericSuperclass()
//Converter
Class[] results = doResolveTypeArguments(ownerClass, classToIntrospect.getGenericSuperclass(), genericIfc);
if (results != null) {
return results;
}
}
classToIntrospect = classToIntrospect.getSuperclass();
}
return null;
}
private static Class[] doResolveTypeArguments(Class ownerClass, Type ifc, Class genericIfc) {
if (ifc instanceof ParameterizedType) {
ParameterizedType paramIfc = (ParameterizedType)ifc;
Type rawType = paramIfc.getRawType();
if (genericIfc.equals(rawType)) {
Type[] typeArgs = paramIfc.getActualTypeArguments();
Class[] results = new Class[typeArgs.length];
for (int i = 0; i < typeArgs.length; i++) {
Type arg = typeArgs[i];
results[i] = extractClass(ownerClass, arg);
}
return results;
} else if (genericIfc.isAssignableFrom((Class)rawType)) {
return doResolveTypeArguments(ownerClass, (Class)rawType, genericIfc);
}
} else if (ifc != null && genericIfc.isAssignableFrom((Class)ifc)) {
return doResolveTypeArguments(ownerClass, (Class)ifc, genericIfc);
}
return null;
}
テストの例 @Test
public void testGenericType() {
StringToBoolean params = new StringToBoolean();
Class[] genericArgs = GenericTypeResolver.resolveTypeArguments(params.getClass(), Converter.class);
Assert.assertEquals(String.class, genericArgs[0]);
Assert.assertEquals(Boolean.class, genericArgs[1]);
}
interface Converter {
}
class StringToBoolean implements Converter {
}