I have the below class structure:
class A<T,R> {
B<R> b;
......
}
class B<R> {
R t;
}
class StringConsumer {
A<String, String> a;
}
class LongConsumer {
A<Long, Long> a;
}
Given that I have an instance of one of the consumer classes, is it possible to obtain the type parameter(s) for consumer.a.b
? I found that I am able to resolve the same if I declare a
as StringA a;
where class StringA extends A<String, String>
using TypeTools
Since your consumer classes declare the field a
with no type variables, all the typing information you need will be present at runtime.
While it's possible to achieve what you're asking using reflection directly, it gets insane fast, so I'd highly recommend using GenTyRef or GeAnTyRef (an enhanced fork that I maintain).
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
So what you do here is start from StringConsumer
, get the type of its field a
(typeOfA
, which is A<String, String>
), then use that information to get the type of field b
(typeOfB
, which is B<String>
).
You can go as deep as you need to this way...