在 Java 6 注解处理器中查找方法返回类型的类型参数

我正在编写一个工具,它使用注释处理器根据带注释的类的方法的返回类型生成源代码.返回类型始终是定义类型变量 T 的接口 A 的某个子类型(接口或类).

I'm writing a tool that uses the annotation processor to generate source code depending on the return type of methods of an annotated class. The return type is always some subtype (interface or class) of an interface A that defines a type variable T.

interface A<T>{T m();};

我想找方法m()返回值类型变量T的类型参数.

I would like to find the type parameter for the method m() return value type variable T.

返回类型由注释处理器表示为 javax.lang.model.type.TypeMirror 实例.最简单的情况是直接返回A<T>.

The return type is represented by the annotation processor as a javax.lang.model.type.TypeMirror instance. The simplest case is to return A<T> directly.

@SomeAnnotation
class SomeClass{
    A<T> x();
}

找出T的处理器代码非常简单.(为了保持代码简单,我将在这里转换而不是使用访问者 API.)

The processor code to find out T is quite simple. (I'll cast instead of using the visitor API here to keep the code simple.)

DeclaredType type = (DeclaredType) typeMirror;
TypeMirror t = type.getTypeArguments().get(0);

返回类型的TypeMirror是一个javax.lang.model.type.DeclaredTypeT是第一个类型参数.结果 tTjavax.lang.model.type.TypeVariable.这同样适用于具体的返回类型 A<B>(B 是某种类型:interface B{}).t 的结果是一个代表 BDeclaredType.

The TypeMirror of the return type is a javax.lang.model.type.DeclaredType and T is the first type argument. The result t is a javax.lang.model.type.TypeVariable for T. The same works for a concrete return type A<B> (B is some type: interface B{}). The result for t is a DeclaredType representing B.

其他结果类型开始变得复杂:

Things start to get complicated with other result types:

interface Subtype<T> extends A<T>{}
interface Concrete extends A<B>{};
interface Multiple<B,T> extends A<T>{}
interface Bounds<T extends B> extends A<T>{}
interface Hierarchy extends Concrete{}

Subtype<B>          -> DeclaredType B
Subtype<T>          -> TypeVariable T
Concrete            -> DeclaredType B
Multiple<B,T>       -> TypeVariable T or DeclaredType B depeding on Multiple
Multiple<B,B>       -> TypeVariable B
<T extends B> A<T>  -> TypeVariable T with super class bound B
Bound<B>            -> DeclaredType B
Bound<C>            -> DeclaredType C (subtype of B)
Hierarchy           -> TypeVariable T

有没有办法在不镜像整个 java 类型系统的情况下为 T 找到正确的类型参数?

Is there a way to find the correct type parameter for T without mirroring the whole java type system?

推荐答案

看看http://docs.oracle.com/javase/6/docs/api/javax/lang/model/util/Types.html#asMemberOf%28javax.lang.model.type.DeclaredType,%20javax.lang.model.element.Element%29

我用它来解决这个问题,并在这个拉取请求中为 WsDoc 项目贡献了解决方案:https://github.com/versly/wsdoc/pull/7

I used it to solve this problem and contributed the solution to the WsDoc project in this pull request: https://github.com/versly/wsdoc/pull/7

我做了这样的事情:

      Type.MethodType methodType = (Type.MethodType) processingEnv.getTypeUtils().asMemberOf(declaredTypeThatExtendsSomeGenericParent, methodToGetReturnTypeForAsExecutableElement);
      TypeMirror type = methodType.getReturnType();

相关文章