Java 在注释中直接使用注释处理器生成的常量将导致编译错误
我有一个Java 在注释中直接使用注释处理器生成的常量将导致编译错误,java,annotations,javac,annotation-processing,Java,Annotations,Javac,Annotation Processing,我有一个HelloWorldProcessor,他只需生成源文件HelloWorldMessage.java public interface HelloWorldMessage { String HELLO_WORLD = "Hello World"; } 现在,我在代码中使用生成的值: public class UseHelloWorld { @Anno(HelloWorldMessage.HELLO_WORLD) public void func(){ } } 那很好
HelloWorldProcessor
,他只需生成源文件HelloWorldMessage.java
public interface HelloWorldMessage {
String HELLO_WORLD = "Hello World";
}
现在,我在代码中使用生成的值:
public class UseHelloWorld {
@Anno(HelloWorldMessage.HELLO_WORLD)
public void func(){
}
}
那很好
但如果我声明该值为常量并间接使用它,则会导致编译错误
public class UseHelloWorld{
public static final String HW = HelloWorldMessage.HELLO_WORLD;
@Anno(UseHelloWorld.HW)
public void func(){
}
}
Javac给出的符号未找到
错误:
UseHelloWorld.java:2: error: cannot find symbol
public static final String HW = HelloWorldMessage.HELLO_WORLD;
^
symbol: variable HelloWorldMessage
location: class UseHelloWorld
UseHelloWorld.java:4: error: element value must be a constant expression
@Anno(UseHelloWorld.HW)
^
2 errors
我之所以说“javac”是因为它在eclipse和ECJ以及m2e-apt中运行良好
这是javac错误吗?如果没有,我怎样才能正确地间接使用生成的源代码?我不知道这个主题,所以尝试了一下。 您的示例似乎不适用于
javac
,按照您提供的步骤,我认为不会调用处理器。您可以尝试使用一些调试参数来验证:
-XprintProcessorInfo
:打印有关要求处理器处理哪些批注的信息-XprintRounds
:打印有关初始和后续注释处理循环的信息-verbose
:详细输出。这包括有关加载的每个类和编译的每个源文件的信息/META-INF/services/javax.annotation.processing.processor
。我尝试过这个方法,虽然更好,但还是失败了,我认为这是因为源文件没有编译,所以编译器无法检索有关注释的任何信息(我认为可以通过扫描源文件)
最后,我通过将注释的使用从UseHelloWorld
移动到package info.java
文件(或任何其他编译文件)来实现。现在,编译器可以看到注释已在源文件中使用,处理器将被调用以生成HelloWorldMessage
类,该类将在下一轮中编译。类UseHelloWorld
也可以编译
注意:我在您的文件中添加了一些import
和package
,否则即使存在HelloWorldMessage
类,它也无法编译
我认为它在Eclipse中工作的原因是使用了不同的工具来进行处理。或者,您可能已经生成了源文件,但忘记了清理它。希望有人能给出更好的答案,我只是分享我的实验
更新 我愚蠢地说,我们应该将处理器作为jar提供,显然一个类文件就足够了(我可能使用了错误的类路径)。我对更新后的帖子的猜测是,编译器并不能处理所有情况。 在Eclipse中,我们看到关于
@Anno
@Anno(HelloWorldMessage.HELLO\u WORLD)
:无法将HelloWorldMessage解析为变量@Anno(UseHelloWorld.HW)
:注释属性Anno.value的值必须是常量表达式可能在第一种情况下,编译器足够聪明,可以猜测注释处理器可以生成未知类型,因此它会进行尝试,在第二种情况下,它会将其视为注释使用不当 尝试通过类ref:@Bean(ClassName.HELLO)访问静态var,我认为根据java版本和处理器类的位置,您应该指定一些javac参数来指示编译器这些参数的位置。对于Java 8:。IDE为您做了很多事情。这并不奇怪,它可以直接与它一起工作。@Eugen,它仍然不是work@davidxxx您知道shuold添加了哪个参数吗?您使用的是什么版本的java和spring?您还可以发布声明为
公共字符串bean()的类吗{
和公共静态最终字符串您好
谢谢您的回答。我在创建最小化测试用例时出错。我已经更新了我的用例。您能再试一次吗,我保证它会工作并且现在失败吗?当我发现它已经过去了5分钟时,我错误地投了反对票。您能编辑您的答案以便我可以恢复我的反对票吗。@DeanXu我已经更新了我的答案,您的示例非常有趣,我实际上认为这是编译器的一个限制。对于这样的常量,编译器将内联它。因此直接和间接用法应该没有区别。我已经向oracle报告了该错误。@DeanXu我不确定这里是否会发生内联,因为将生成HelloWorldMessage
。我在这个阶段,编译器只检索有关注释类型的信息进行处理。