I have this example setup:
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()");
}
}
So, I can now do this:
$ 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()
No problem, the annotations are optional and ignored by the runtime, no NoClassDefFoundError
However, when I remove the source files of p
as well, keeping the compiled Test.class
:
$ rm -Rf p
And then create:
x.Test2
package x;
public class Test2 {
q.Test test;
}
Compiling that class gives a warning:
$ javac x/Test2.java
warning: unknown enum constant E.E
reason: class file for p.E not found
1 warning
Alternatives, that don't produce such a warning
No enum
I don't get this warning for an annotation that doesn't depend on any enums. I.e. repeat the procedure for these, and there's no 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()");
}
}
Class reference
When A
references Class<E>
instead of an E.E
enum value, I still don't get any warnings:
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()");
}
}
My questions:
- Is this a correct warning according to the JLS? It seems like a bug in javac to me, given the annotation is optional and doesn't produce a warning if there's no
enum
type involved, but I may be missing something. - Is there any way to work around this warning in client code?
For context: the real world use-case is:
- The
p
package containing the annotations are from JAXB - The
q
package containing library code that references the annotations is a library whose dependency onp
is optional. (jOOQ to be specific, more details here) - The
x
package is client code, depending on theq
package, which has an optional dependency onp
, meaning, the dependency is effectively missing by default.