我有这个示例设置:
100
package p;
public enum E { E }
100
package p;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
public @interface A {
p.E e();
}
100
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
然后创建:
100
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
替代方案,不会产生这样的警告
没有枚举
对于不依赖于任何枚举的批注,我没有收到此警告.即对这些重复该过程,则不会出现任何警告:
100
package p;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
public @interface A {}
100
package q;
import p.*;
@A
public class Test {
public static void main(String[] args) {
System.out.println("Test.main()");
}
}
类引用
当A
引用Class<E>
而不是E.E
枚举值时,我仍然没有收到任何警告:
100
package p;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
public @interface A {
Class<?> a();
}
100
package q;
import p.*;
@A(a = E.class)
public class Test {
public static void main(String[] args) {
System.out.println("Test.main()");
}
}
我的问题:
- 根据JLS的说法,这是一个正确的警告吗?在我看来,这似乎是javac中的一个错误,因为注释是可选的,如果不涉及
enum
类型,则不会产生警告,但我可能遗漏了一些东西. - 有什么方法可以在客户端代码中解决此警告吗?
For context: the real world use-case is:个
- 包含注释的
p
个包来自JAXB - 包含引用注释的库代码的
q
包是一个对p
的依赖是可选的库.(具体来说,jOOQ为more details here) -
x
包是客户端代码,这取决于q
包,它对p
有一个可选的依赖项,这意味着在默认情况下,该依赖项实际上是缺失的.