我正在用 Java 8 编写注释处理器。
假设我在项目的某处有这样的课程:
public class SampleClass {
public void foo(int i) {
new Runnable() {
@Override
public void run() {
System.out.println(i);
}
};
}
}
在我的代码中的某处else,我有我的注释,包含 SampleClass 的完全限定名称和编译后标识匿名类的唯一整数(如 SampleClass$id 中)。
要执行我的任务,我需要找到代表该特定匿名类的
javax.lang.model.element.Element
对象。或者,除此之外,至少获取代表某个类中的匿名类的 Element
对象的列表将是一个开始。我很确定这是可能的,因为在 javax.lang.model
包的文档中多次引用了匿名类,但我不知道在我的案例中你会如何具体地得到它们。
我确实尝试了最明显的事情。假设我想编写一个方法,给定一个类的完全限定名称 (
fqn
) 和一个 ProcessingEnvironment
对象 (env
),构建该元素中包含的所有匿名类的列表(并且,递归地,它的每个子元素,以及它们的子元素,等等)。这是我最好的猜测:
public List<Element> findAnonymousClasses(String fqn, ProcessingEnvironment env) {
Element sampleClassElement = processingEnvironment.getElementUtils().getTypeElement(fqn);
List<Element> anons = new ArrayList<>();
sampleClassElement.getEnclosedElements()
.forEach(e -> {
if(e.getSimpleName().length() == 0)
anons.add(e);
anons.addAll(getAnonymousClasses(e, env));
});
}
我的推理是
getSimpleName()
,根据其文档:
如果它表示一个匿名类或实例初始化器,则返回一个空名称。
和
空的 {@code Name} 的长度为零。
代码显然有缺陷,因为它也会在类的方法中返回匿名类,但它至少应该返回一些东西!然而,显然,
List
是空的。将 e.getSimpleName().length() == 0
替换为 e instanceof TypeElement && ((TypeElement) e).getNestingKind() == NestingKind.ANONYMOUS
会产生相同的结果。
进一步检查发现问题不在于我如何过滤它。相反,
Element.getEnclosedElements()
似乎从不包含匿名类。那我怎么才能找到他们呢?当然,如果在(即NestingKind.ANONYMOUS
)中编码了对它们的处理,那么它们必须以某种方式获得吗?希望这里的任何人都能给我一个正确的方向。