GenericsUtil { public static Optional<Type> getTypeParameterBinding(Type target, int index) { Class<?> classOfType = getClassOfType(target); if (classOfType != null) { return getTypeParameterBindingForInheritedClass(target, classOfType, index); } throw new IllegalArgumentException("Unsupported type: " + target); } 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 noTypeParameterForUnboundInterfaceField() throws Exception { Type t = GenericsUtilTest.class.getDeclaredField("unboundInterface").getGenericType(); assertFalse(GenericsUtil.getTypeParameterBinding(t, 0).isPresent()); }
@Test public void correctParameterForBoundInterfaceField() throws Exception { Type t = GenericsUtilTest.class.getDeclaredField("boundInterface").getGenericType(); Optional<Type> result = GenericsUtil.getTypeParameterBinding(t, 0); assertTrue(result.isPresent()); assertEquals(String.class, result.get()); }
@Test public void noTypeParameterForUnboundClassField() throws Exception { Type t = GenericsUtilTest.class.getDeclaredField("unboundClass").getGenericType(); assertFalse(GenericsUtil.getTypeParameterBinding(t, 0).isPresent()); }
@Test public void correctParameterForBoundClassField() throws Exception { Type t = GenericsUtilTest.class.getDeclaredField("boundClass").getGenericType(); Optional<Type> result = GenericsUtil.getTypeParameterBinding(t, 0); assertTrue(result.isPresent()); assertEquals(String.class, result.get()); }
@Test(expected = IndexOutOfBoundsException.class) public void exceptionIfParameterIsOutOfBounds() throws Exception { Type t = GenericsUtilTest.class.getDeclaredField("boundInterface").getGenericType(); GenericsUtil.getTypeParameterBinding(t, 1); }
@Test(expected = IllegalArgumentException.class) public void exceptionIfSuperClassIsNotParameterized() throws Exception { Type t = GenericsUtilTest.class.getDeclaredField("nonGenericInterface").getGenericType(); GenericsUtil.getTypeParameterBinding(t, 0); }