Я создал метод, который будет возвращать вам массив типов, которые параметризовали общий тип, где «ноль» указывает на параметры, которые все еще существуют.Я проверил это в соответствии с вашей иерархией Foo, а также в примере, представленном в другом ответе, который использует класс «A».
Редактировать: Прежде чем я не думал, как будет переупорядочивать типыповлиять на привязку.В новом методе передайте суперкласс, параметры которого вы хотите, и базовый класс.По мере итерации к суперклассу я собираю параметры типа, являющиеся классами, и отображаю их в предыдущем базовом классе, сравнивая имена параметров.Я надеюсь, что это достаточно ясно.
public <S, B extends S> Class[] findTypeParameters(Class<B> base, Class<S> superClass) {
Class[] actuals = new Class[0];
for (Class clazz = base; !clazz.equals(superClass); clazz = clazz.getSuperclass()) {
if (!(clazz.getGenericSuperclass() instanceof ParameterizedType))
continue;
Type[] types = ((ParameterizedType) clazz.getGenericSuperclass()).getActualTypeArguments();
Class[] nextActuals = new Class[types.length];
for (int i = 0; i < types.length; i++)
if (types[i] instanceof Class)
nextActuals[i] = (Class) types[i];
else
nextActuals[i] = map(clazz.getTypeParameters(), types[i], actuals);
actuals = nextActuals;
}
return actuals;
}
private Class map(Object[] variables, Object variable, Class[] actuals) {
for (int i = 0; i < variables.length && i < actuals.length; i++)
if (variables[i].equals(variable))
return actuals[i];
return null;
}
@Test
public void findsTypeOfSuperclass() throws Exception {
assertThat(findTypeParameters(A4.class, A1.class), arrayContaining(Integer.class, Boolean.class, String.class));
assertThat(findTypeParameters(B4.class, A1.class), arrayContaining(Integer.class, Boolean.class, String.class));
assertThat(findTypeParameters(C2.class, A1.class), arrayContaining(Integer.class, null, null));
assertThat(findTypeParameters(D4.class, A1.class), arrayContaining(Integer.class, null, String.class));
}
class A1<T1, T2, T3> {}
class A2<T3, T2> extends A1<Integer, T2, T3> {}
class A3<T2> extends A2<String, T2> {}
class A4 extends A3<Boolean> {}
class B2<X, T3, Y, T2, Z> extends A1<Integer, T2, T3> {}
class B3<X, T2, Y, Z> extends B2<X, String, Y, T2, Z> {}
class B4<X> extends B3<X, Boolean, X, X> {}
class C2<T2, T3> extends A1<Integer, T2, T3> {}
class D2<T2> extends A1<Integer, T2, String> {}
class D3 extends D2 {}
class D4 extends D3 {}