在编译时获取处理器内部方法调用(ExecutableElement)的参数类

时间:2018-06-16 16:34:31

标签: java

我有一个类,在其中我有一个方法,在编译时使用处理器处理自定义注释。

@Controller
public class ExampleController {

    @ListenFor
    public void handleRequest(Object something, String other) {

    }
}

我想验证方法期望的第二个参数的类,并确保它是String

在处理器内部,我获取方法的可执行元素并从中获取参数作为VariableElements:

ExecutableElement exeElement = (ExecutableElement) e;

List<? extends VariableElement> params = exeElement.getParameters();

如何在处理器内的编译时获取第二个参数(String other)的类,以便将它与String类进行比较并验证它?

1 个答案:

答案 0 :(得分:2)

由于您在编译时运行,因此您不一定要依赖Class个实例。相反,编译时类型还有另一种表示形式,称为TypeMirror

我们可以通过Element获得Element#asType()TypeMirror。由于上述原因,无法从Class获取TypeMirror个对象。为了检查第二个参数是否为String,我们需要将String.class转换为TypeMirror。方法Elements#getTypeElement(CharSequence name)给出了TypeMirror,给出了一个名称。我们可以通过Class#getCanonicalName()获取Class实例的规范名称。

这导致以下代码:

// assuming the processingEnvironment got passed to the method.
// It is a good idea to store the elementUtil somewhere
// globally accessible during annotation processing.
Elements elementUtils = processingEnvironment.getElementUtils();
...
TypeMirror stringType =
    elementUtils.getTypeElement(String.class.getCanonicalName()).asType();
...
ExecutableElement exeElement = (ExecutableElement) e;
List<? extends VariableElement> params = exeElement.getParameters();
TypeMirror secondArgumentType = params.get(1).asType();

// I find the explicit version has a less cognitive complexity. Feel free to change it.
if (secondArgumentType.equals(stringType) == false) { 
    // TODO: halt and catch fire!
}

// from here on, you can be certain that the second argument is a String.
...