汎用インターフェースを実現する具体的なクラスの実装のタイプを取得します。

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 {
		
	}