Erric
Erric

Reputation: 797

Reflection: Applying type parameters of declaring class to fields

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

Upvotes: 0

Views: 223

Answers (1)

kaqqao
kaqqao

Reputation: 15499

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...

Upvotes: 1

Related Questions