maven 中 javac 编译顺序错误的解决方法

2022-09-02 13:59:44

我在Java编译器中遇到了一个错误,其中提交以进行编译的文件的顺序可能导致代码无法编译。我深入研究了代码,以隔离重现问题的最小代码量,从而生成三个源文件(每个 1 个类)。

public interface ActionSpec {
    public abstract int run(String param);
}


public enum Actions implements ActionSpec {
    SKIP {
        public int run(String d) {
            return 0;
        }
    };
}

public class Program {

    public static void main(String[] args) {
        Actions.SKIP.run("hello");
    }
}

通过以特定顺序使用javac参数,可以重现该问题。简而言之,为了成功,Actions类必须始终在使用它的程序类之前编译,否则javac就无法以理智的方式处理它:

# this case fails
echo "Trying order: javac Program.java Actions.java ActionSpec.java"
rm *class
javac -verbose Program.java Actions.java ActionSpec.java

# this case fails
#rm *class
#javac Program.java Actions.java ActionSpec.java

# this case fails
#rm *class
#javac ActionSpec.java Program.java Actions.java

# this case succeeds
#rm *class
#javac ActionSpec.java Actions.java Program.java

# this case succeeds
#rm *class
#javac Actions.java ActionSpec.java Program.java

# this case succeeds
#rm *class
#javac Actions.java Program.java ActionSpec.java

编译错误(当它发生时)始终是相同的 - 找不到 Actions 枚举实例上的 run 方法,即使它们都实现了具有该 run 方法的接口。

Program.java:6: cannot find symbol
symbol  : method run(java.lang.String)
location: class problem.Actions
        Actions.SKIP.run("hello");

该错误似乎与Oracle网站上报告的这个错误有关。我在mac os x 10.7.2上使用javac 1.6.0_29,x86_64,但也在Linux上复制了它。

当我使用Maven进行构建时,这个问题变得很明显,并且似乎无法控制编译顺序。因此,我正在寻找一种解决方法,要么强制maven以这样的顺序编译文件以避免此编译器错误,要么摆弄编译器标志(或类似的东西)以避免它。这个问题在工作站和持续集成环境中都会出现,因此它必须全面工作。有什么建议吗?

编辑:刚刚尝试了以下解决方法,尽管仅将有问题的枚举分配给具有其实现的接口类型的变量,但令人惊讶的是导致错误消失。

public class Program {

    public static void main(String[] args) {
        ActionSpec a = Actions.SKIP;
        a.run("hello");
    }
}

仍然对别人的意见感兴趣。


答案 1

我玩了一下,发现添加简单的演员:

public static void main(String[] args) {
    ((ActionSpec)Actions.SKIP).run("hello");
}

解决了这个问题。将此枚举作为方法参数作为接口传递也将解决问题


答案 2

这是 http://bugs.sun.com/view_bug.do?bug_id=6724345 中报告的错误

如果您仍在使用 Java 6 编译器,则建议的解决方法应该有效。该错误已在 Java 7 中修复。


推荐