执行Java AnnotationProcessor时发生ClassNotFound异常

执行Java AnnotationProcessor时发生ClassNotFound异常,java,annotations,Java,Annotations,我编写了一个简单的注释和一个AnnotationProcessor来处理注释 注释只有一个值:它应该是现有接口(带有包)的名称 注释处理器应该检索注释的值,检索接口的类对象,最后应该打印接口中声明的所有方法 例如: 这是我的注解 @Target(ElementType.TYPE) @Retention(RetentionPolicy.CLASS) public @interface MyAnnotation{ public String interfaceName(); } 这是注释类

我编写了一个简单的注释和一个AnnotationProcessor来处理注释

注释只有一个值:它应该是现有接口(带有包)的名称

注释处理器应该检索注释的值,检索接口的类对象,最后应该打印接口中声明的所有方法

例如: 这是我的注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface MyAnnotation{
    public String interfaceName();
}
这是注释类:

@MyAnnotation(interfaceName = "java.lang.CharSequence")
public class Example{}
我的处理器看起来像

[...]
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) {

    for (TypeElement te : annotations) {

        for(Element e : env.getElementsAnnotatedWith(te)) {

            MyAnnotation myAnnotation = e.getAnnotation(MyAnnotation.class);
            String iName = myAnnotation.interfaceName();
            Class<?> clazz = Class.forName(iName);
            // use reflection to cycle through methods and prints them
            [...]
        }
    }
[…]

公共布尔进程(Set这是一个典型的类加载器问题。您试图查找当前类加载器未加载的类,因此会引发
ClassNotFoundException

for
java.lang.Class
将方法
Class.forName(className)
定义为:

返回与具有给定字符串名称的类或接口关联的类对象。调用此方法相当于
Class.forName(className,true,currentLoader)
,其中currentLoader表示当前类的定义类装入器

因此,此方法调用将尝试在当前类加载器上下文中查找指定的类。您尝试查找的接口尚未由此类加载器加载,因此会引发
ClassNotFoundException

如果
.jar
文件位于应用程序的类路径上,您可以简单地使用系统类加载器,如下所示

ClassLoader systemClassLoader = ClassLoader.getSystemClassloader();
Class<?> clazz = Class.forName(className, true, systemClassLoader)

Et voilía!

这可能是注释处理工作方式的问题。使用是否返回非null的
TypeElement
?嗨,斯拉夫,谢谢你的回答。我做了TypeElement TypeElement=this.processingEnv.getElementUtils().getTypeElement(myAnnotation.interfaceName());并且typeElement不为null。在这种情况下,您最好通过注释处理API(即通过
typeElement
)访问有关类的信息.Hi Slaw,是的,我试图使用该API,但我没有找到任何方法来读取方法的返回类型或参数列表。相反,使用Java反射非常容易…使用注释处理器API确定方法的参数类型和返回类型,您需要获得适当的。请检查该类的方法。注意,however、 我并不是说在这种情况下必须使用注释处理器API。嗨,Daniel,谢谢你的回答。好的,类加载器的问题已经很清楚了,所以我按照你在clazz=Class.forName类(className,true,ClassLoader.getSystemClassLoader())中的建议更改了代码行;然而,问题仍然存在。也许问题就在这里:“如果.jar文件位于应用程序的类路径上,您可以简单地使用系统类加载器”我使用Eclipse作为IDE,我将.jar添加到“构建路径”,而不是“类路径”(idk区别)…我尝试使用URLClassLoader,它发现了类:)但是,我不明白为什么SystemClassLoader找不到它,.jar在项目的构建路径中…@user1561017有点混乱,请允许我解释一下。buildpath和classpath是两个独立的东西。Eclipse使用构建路径解析IDE中的类。构建路径用于编译,并为IDE提供丰富的功能。运行时重要的是类路径;类路径用于解析JVM中加载的
.class
文件。JVM实际上不知道Eclipse构建路径的内容。它只关心类路径。嗨,丹尼尔,再次感谢你的解释。然而,这打开了另一个问题:)如何使用Eclipse将给定的jar添加到项目的“类路径”中?我只能找到将jar添加到“buildpath”的选项。。。非常感谢你
ClassLoader urlClassLoader = new URLClassLoader(new URL[]{new URL("path/to/file.jar")});
Class<?> clazz = Class.forName(className, true, urlClassLoader)