Extracting the concrete type argument from a type extending a generic type in java annotation processors

238 views Asked by At

Consider I have a type:

interface Foo<T> {
  boolean foo();
}

And I create BarFoo like so:

class BarFoo implements Foo<Bar> {
  boolean foo();
}

In a Java6 Annotation Processor, with access to the TypeElement BarFoo, how can I discover the concrete type with which this non-generic subclass was parameterized in the context of implementing Foo (specifically Bar).

And how, further, when I have a more complex hierarchy, like so:

interface Foo<T> {
  boolean foo();
}

class BarFoo implements Foo<Bar> {
  boolean foo();
}

class Grandchild extends BarFoo {}

How, given Grandchild's TypeElement could I find out the type of the type parameter of Foo?

Please note - I do not need to know the reflection APIs that will do this, but specifically the javax.lang.model and javax.annotation.processing APIs that will get me to Bar in this scenario.

Edit: I changed the return type from T to boolean, because in my real-world case, I don't have any method that returns T that might prove a workaround. I need to get it from the type hierarchy, not from method return types, sadly.

1

There are 1 answers

2
lexicore On

I would try:

  • TypeElement.getInterfaces() -> List<? extends TypeMirror>
  • TypeMirror.accept(...) visitor which checks for DeclaredType
  • DeclaredType.getTypeArguments() -> List<? extends TypeMirror> which should give you a TypeElement for Bar

For the Grandchild probably the same scheme, but first getSuperclass().

Another option is to go from Foo, check getTypeParameters() which would give you T and then look for a method which has T as getReturnType() and then look for the implementations of that method (probably not so easy if you consider the signature and not just name) and finally find out which return type has the implementation. But this is way more complex.