Given 2 interfaces:
public interface BaseInterface<T> { }
public interface ExtendedInterface<T0, T1> extends BaseInterface<T0> {}
and a concrete class:
public class MyClass implements ExtendedInterface<String, Object> { }
How do I find out the type parameter passed to the BaseInterface interface?
(I can retrieve the ExtendedInterface type parameters by calling something like
MyClass.class.getGenericInterfaces()[0].getActualTypeArguments()
but I can't spot an easy way to recurse into any base generic interfaces and get anything meaningful back).
This problem is not easy to fully solve in general. For example, you also have to take type parameters of the containing class into account if it's an inner class,...
Because reflection over generic types is so hard using just what Java itself provides, I wrote a library that does the hard work: gentyref. See http://code.google.com/p/gentyref/ For your example, using gentyref, you can do:
This kinda does what you are after, but it's still not right. For instance, it doesn't handle the case where
Foo<T> implements Bar<Map<T>>
. What you really need is some way to ask the jvm "ok, here is a list of types. What actual type do I get back if I apply these to this generic type?"But, this code kinda does what you are after.
This is difficult to solve using Java Reflection API because one needs to resolve all encountered type variables. Guava since version 12 has TypeToken class which contains fully resolved type info.
For your example, you can do:
Still you need to remember that this only works for cases when MyClass is not generic itself. Otherwise the value of type parameters is not available at runtime due to type erasure.
I don't think there's an direct way of getting the generic type of the base interface.
One way would be to declare a method in the interface like this:
Also, I don't know what kind of control you have over these classes. You can always assert that all implementers have the base interface explicitly declared like:
and
bad etiquette again from me answering my own question.
As gix pointed out, the moment you start walking up a hierarchy of generic types, beyond the first, you lose information about type arguments.
But the important bits are: You get the type arguments of the first generic interface to be instanced (in my example, ExtendedInterface), and you also get the names of the type parameters used to create the sub-interfaces.
So, it is possible to determine the type arguments to base interfaces by keeping a map of TypeVariable names to actual type arguments.
I will update with some code later, but it does work (you can determine the type parameter used to instance BaseInterface, from MyClass.class).
Update This is a first pass that green lights some simple unit tests. It needs work... The real question is, does the problem merit such a ludicrous solution?
}
I don't know what exactly you are trying to achieve, and what is known and what not, but you can recurse to the superinterface like this:
Of course if you reach the second level that way you get only your names T0 and T1 as generic parameters. If you know the relationship between
ExtendedInterface
andBaseInterface
you don't really have to go that far since you know which generic parameter of the former is passed to the latter. If not, you probably would have to loop through their parameters and find a match. Something based on this probably: