如何避免 javac 警告:未知枚举常量,原因:未找到类文件,当依赖项具有带有枚举的可选注释时

Luk*_*der 20 java annotations javac

我有这个示例设置:

p.E

package p;

public enum E { E }
Run Code Online (Sandbox Code Playgroud)

p.A

package p;

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
public @interface A {
    p.E e();
}
Run Code Online (Sandbox Code Playgroud)

q.Test

package q;

import p.*;

@A(e = E.E)
public class Test {
    public static void main(String[] args) {
        System.out.println("Test.main()");
    }
}
Run Code Online (Sandbox Code Playgroud)

所以,我现在可以这样做:

$ 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()
Run Code Online (Sandbox Code Playgroud)

没问题,注释是可选的并且被运行时忽略,没有NoClassDefFoundError

但是,当我也删除源文件时p,保留编译后的Test.class

$ rm -Rf p
Run Code Online (Sandbox Code Playgroud)

然后创建:

x.Test2

$ rm -Rf p
Run Code Online (Sandbox Code Playgroud)

编译该类会发出警告:

package x;

public class Test2 {
    q.Test test;
}
Run Code Online (Sandbox Code Playgroud)

不会产生此类警告的替代方案

无枚举

对于不依赖于任何枚举的注释,我没有收到此警告。即重复这些过程,并且没有警告:

p.A

$ javac x/Test2.java
warning: unknown enum constant E.E
  reason: class file for p.E not found
1 warning
Run Code Online (Sandbox Code Playgroud)

q.Test

package p;

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
public @interface A {}
Run Code Online (Sandbox Code Playgroud)

类参考

A引用Class<E>而不是E.E枚举值时,我仍然没有收到任何警告:

p.A

package q;

import p.*;

@A
public class Test {
    public static void main(String[] args) {
        System.out.println("Test.main()");
    }
}
Run Code Online (Sandbox Code Playgroud)

q.Test

package p;

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
public @interface A {
    Class<?> a();
}
Run Code Online (Sandbox Code Playgroud)

我的问题:

  1. 根据 JLS 的说法,这是正确的警告吗?对我来说,这似乎是 javac 中的一个错误,因为注释是可选的,并且如果不涉及类型则不会产生警告enum,但我可能会遗漏一些东西。
  2. 有什么方法可以解决客户端代码中的此警告吗?

对于上下文:现实世界的用例是:

  • 包含注释的包p来自 JAXB
  • q包含引用注释的库代码的包是一个库,其依赖项是p可选的。(具体为 jOOQ,更多详细信息请参见此处
  • x包是客户端代码,具体取决于q包,它具有对 的可选依赖项p,这意味着默认情况下该依赖项实际上是缺失的。

Luk*_*der 2

正如用户 yyyy以及库 bug tracker上的评论,当前行为是由修复JDK-6550655定义的,该修复在 Java 7 中引入了警告(之前,此注释/枚举的使用导致了编译错误)。

JDK-6550655略有不同。p.E该警告是针对仅缺少枚举而不缺少注释的情况引入的p.A,在这种情况下,p.A使用反射 API 访问时确实会出现不希望的运行时错误。警告开发人员这种情况当然是值得的。然而,在这种情况下,p包的所有内容都不存在,这意味着不会有任何运行时错误,并且根据注释的设计,不存在应该没问题,允许不存在。

在我看来,这是 javac 中的一个错误,我已经报告了:JDK-8305250。它可能会也可能不会被接受或修复。