Поскольку ваши потребительские классы объявляют поле a
без переменных типа, вся необходимая информация о наборе будет присутствовать во время выполнения.
Хотя можно достичь того, что вы просите, используя прямое отражение, оно быстро становится безумным, поэтому я настоятельно рекомендую использовать GenTyRef или GeAnTyRef (расширенный форк, который я поддерживать).
StringConsumer consumer = new StringConsumer(); //Or LongConsumer
Field a = consumer.getClass().getDeclaredField("a");
//typeOfA represents A<String, String>
ParameterizedType typeOfA = (ParameterizedType) GenericTypeReflector.getExactFieldType(a, consumer.getClass());
Type[] args = typeOfA.getActualTypeArguments();
System.out.println(args[0]); //String
System.out.println(args[1]); //String
Field b = A.class.getDeclaredField("b");
//or if you need it dynamic ((Class)typeOfA.getRawType()).getDeclaredField("b")
//or GenericTypeReflector.erase(typeOfA).getDeclaredField("b")
//typeOfB represents B<String>
ParameterizedType typeOfB = (ParameterizedType) GenericTypeReflector.getExactFieldType(b, typeOfA);
System.out.println(typeOfB.getActualTypeArguments()[0]); //String again
Итак, что вы здесь делаете, начинаете с StringConsumer
, получаете тип его поля a
(typeOfA
, то есть A<String, String>
), затем используйте эту информацию для получения типа поля b
( typeOfB
, что B<String>
).
Вы можете пойти так глубоко, как вам нужно ...