如何避免依赖含枚举的可选注解时javac报未知枚举常量警告
问题背景与示例
搭建的示例环境
p.E
package p; public enum E { E }
p.A
package p; import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) public @interface A { p.E e(); }
q.Test
package q; import p.*; @A(e = E.E) public class Test { public static void main(String[] args) { System.out.println("Test.main()"); } }
执行操作与初始结果
执行以下命令:
$ javac q/Test.java $ rm p/*.class $ ll */* -rw-r--r-- 1 lukas 197609 118 Mar 28 10:21 p/A.java -rw-r--r-- 1 lukas 197609 32 Mar 28 09:43 p/E.java -rw-r--r-- 1 lukas 197609 486 Mar 28 10:22 q/Test.class -rw-r--r-- 1 lukas 197609 153 Mar 28 09:55 q/Test.java $ java q/Test Test.main()
此时运行正常,注解属于可选内容,运行时会被忽略,不会抛出NoClassDefFoundError。
触发警告的场景
移除p包的所有源文件,仅保留编译后的Test.class:
$ rm -Rf p
创建x.Test2:
package x; public class Test2 { q.Test test; }
编译该类时出现警告:
$ javac x/Test2.java warning: unknown enum constant E.E reason: class file for p.E not found 1 warning
不会触发警告的替代方案
不使用枚举
如果注解不依赖枚举,重复上述操作不会出现警告:
p.A
package p; import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) public @interface A {}
q.Test
package q; import p.*; @A public class Test { public static void main(String[] args) { System.out.println("Test.main()"); } }
使用类引用
如果注解A引用Class<E>而非直接使用E.E枚举值,同样不会触发警告:
p.A
package p; import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) public @interface A { Class<?> a(); }
q.Test
package q; import p.*; @A(a = E.class) public class Test { public static void main(String[] args) { System.out.println("Test.main()"); } }
问题
- 根据JLS(Java语言规范),这个警告是否合规?考虑到注解是可选的,且无枚举时不会触发警告,我认为这是javac的bug,但可能有遗漏的细节。
- 客户端代码有没有办法规避这个警告?
实际场景说明
- 包含注解的
p包来自JAXB - 引用注解的
q包是一个对p包依赖为可选的库(具体为jOOQ) x包为客户端代码,依赖q包,而q包对p包的依赖默认缺失
内容的提问来源于stack exchange,提问作者Lukas Eder
相关产品推荐
相关产品推荐

