java - 在注解中直接使用注解处理器生成的常量会导致编译错误
问题描述
我有一个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 给出symbol not found
错误:
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'是因为它在带有ECJ和m2e-apt的eclipse中运行良好。
这是一个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
- with
@Anno(HelloWorldMessage.HELLO_WORLD)
: HelloWorldMessage 无法解析为变量 - with
@Anno(UseHelloWorld.HW)
:注解属性 Anno.value 的值必须是常量表达式
也许在第一种情况下,编译器足够聪明地猜测注释处理器可以生成未知类型,所以它会尝试,而在第二种情况下,它会将其视为注释使用不正确。
推荐阅读
- java - Android:如何让活动调用类
- asp.net-mvc - 预检请求在 IIS 中不起作用
- java - 创建了两个条件 While 循环,一个条件与另一个条件一样会导致无限循环
- java - 如何在 JAVA 中使用 XMLDecoder 反序列化 XML
- c# - 我想要一个在 y 轴上倾斜的对象沿着 Z 轴移动?
- c# - 我可以使用 LINQ GroupBy 更干净地执行此操作吗?
- django - @classmethod 错误:TypeError:__call__() 接受 2 个位置参数,但给出了 3 个
- android - Android从后台堆栈中删除事务
- java - 经过几次迭代后,JDBC ResultSet 在 Java 中关闭
- windows - 如何在我的 git-cmd.exe 终端中显示当前分支?