GenericsUtil { public static <T> Optional<Type> getTypeParameterBindingForInheritedClass(Type target, Class<T> superClass, int index) { if (superClass.getTypeParameters().length == 0) { throw new IllegalArgumentException("Class '" + superClass + "' is not parameterized"); } Class<?> classOfType = getClassOfType(target); if (classOfType == null) { throw new IllegalArgumentException("Unsupported type: " + target); } if (!superClass.isAssignableFrom(classOfType)) { throw new IllegalArgumentException("Class '" + target + "' does not implement '" + superClass + "'"); } Type type = GenericTypeReflector.getExactSuperType(target, superClass); if (type instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) type; Type paramType = parameterizedType.getActualTypeArguments()[index]; if (paramType instanceof Class || paramType instanceof ParameterizedType) { return Optional.of(paramType); } } return Optional.empty(); } private  GenericsUtil(); static Optional<Type> getTypeParameterBinding(Type target, int index); static Optional<Type> getTypeParameterBindingForInheritedClass(Type target, Class<T> superClass, int index); static Class<?> getClassOfType(Type type);  }
@Test public void boundInInheritedInterface() throws Exception { Optional<Type> result = GenericsUtil.getTypeParameterBindingForInheritedClass(BoundInterface.class, Predicate.class, 0); assertTrue(result.isPresent()); assertEquals(String.class, result.get()); }
@Test public void boundInInheritedClass() throws Exception { Optional<Type> result = GenericsUtil.getTypeParameterBindingForInheritedClass(BoundClass.class, Predicate.class, 0); assertTrue(result.isPresent()); assertEquals(String.class, result.get()); }
@Test public void boundOneStepRemoved() throws Exception { Type t = GenericsUtilTest.class.getDeclaredField("boundAbstractClass").getGenericType(); Optional<Type> result = GenericsUtil.getTypeParameterBindingForInheritedClass(t, Predicate.class, 0); assertTrue(result.isPresent()); assertEquals(String.class, result.get()); }