ReflectionUtils { public static Type[] getParameterTypes(Class implementation, Class parametrizedInterface) { Type genericInterface = null; List<Class> classesStack = new LinkedList<Class>(); classesStack.add(implementation); while (genericInterface == null) { genericInterface = findGenericInterface(implementation, parametrizedInterface); if (implementation == Object.class && genericInterface == null) { throw new IllegalArgumentException("Class " + implementation.getSimpleName() + " does not implement " + parametrizedInterface.getSimpleName() + " interface."); } if (implementation != Object.class) { implementation = implementation.getSuperclass(); classesStack.add(implementation); } } if (genericInterface instanceof ParameterizedType) { return findRealTypeArguments(genericInterface, classesStack); } throw new IllegalArgumentException("Interface " + parametrizedInterface.getSimpleName() + " is not parametrized"); } private  ReflectionUtils(); static Class getWrapperClassForPrimitive(Class primitiveClass); static Class getPrimitiveForWrapper(Class wrapperClass); static Type[] getParameterTypes(Class implementation, Class parametrizedInterface); static T chooseBestClassStrategy(Map<Class, T> strategies, Class requiredType); @SuppressWarnings("unchecked") static T findAnnotation(Annotation[] annotations, Class<T> annotationType); static final int COLLECTION_ELEMENT_PARAMETER_INDEX; static final int MAP_ELEMENT_PARAMETER_INDEX; }
@Test public void getParameterTypesCorrectlyDirectImplementation() { Type[] parameterTypes = ReflectionUtils.getParameterTypes(BaseExceptionHandler.class, ActionExceptionHandler.class); assertEquals(RuntimeException.class, parameterTypes[0]); }
@Test public void getParameterTypesCorrectlySubclassImplementation() { Type[] parameterTypes = ReflectionUtils.getParameterTypes(SubExceptionHandler.class, ActionExceptionHandler.class); assertEquals(RuntimeException.class, parameterTypes[0]); }
@Test public void getParameterTypesCorrectlySubclassImplementationWithTypedAbstractClass() { Type[] parameterTypes = ReflectionUtils.getParameterTypes(SubExceptionHandler2.class, ActionExceptionHandler.class); assertEquals(IllegalAccessException.class, parameterTypes[0]); }
@Test public void getParameterTypesCorrectlySubclassImplementationWithTwoTypedAbstractClasses() { Type[] parameterTypes = ReflectionUtils.getParameterTypes(SubExceptionHandlerFromLessAbstract.class, ActionExceptionHandler.class); assertEquals(BristleRuntimeException.class, parameterTypes[0]); }