Maven中Javac编译顺序错误的解决方法 - java

我在Java编译器中遇到一个错误,该错误中提交用于编译的文件顺序可能导致代码无法编译。我对代码进行了深入研究,以找出可以重现该问题的最小代码量,从而生成了three source files(每个类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类的Program类之前对其进行编译,否则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");

该错误似乎与this one reported on Oracle's site有关。
我在mac os x 10.7.2 x86_64上使用javac 1.6.0_29,但也在Linux上重现了它。

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

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

public class Program {

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

仍然对其他意见感兴趣。

参考方案

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

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

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

Java:正则表达式模式匹配器是否有大小限制? - java

我的模式类似于OR:“word1 | word2 | word3”我大约有800个字。可能有问题吗? 参考方案 您仅受记忆和理智的限制。 :)

Java:线程池如何将线程映射到可运行对象 - java

试图绕过Java并发问题,并且很难理解线程池,线程以及它们正在执行的可运行“任务”之间的关系。如果我创建一个有10个线程的线程池,那么我是否必须将相同的任务传递给池中的每个线程,或者池化的线程实际上只是与任务无关的“工人无人机”可用于执行任何任务?无论哪种方式,Executor / ExecutorService如何将正确的任务分配给正确的线程? 参考方案 …

JAVA:字节码和二进制有什么区别? - java

java字节代码(已编译的语言,也称为目标代码)与机器代码(当前计算机的本机代码)之间有什么区别?我读过一些书,他们将字节码称为二进制指令,但我不知道为什么。 参考方案 字节码是独立于平台的,在Windows中运行的编译器编译的字节码仍将在linux / unix / mac中运行。机器代码是特定于平台的,如果在Windows x86中编译,则它将仅在Win…

java:继承 - java

有哪些替代继承的方法? java大神给出的解决方案 有效的Java:偏重于继承而不是继承。 (这实际上也来自“四人帮”)。他提出的理由是,如果扩展类未明确设计为继承,则继承会引起很多不正常的副作用。例如,对super.someMethod()的任何调用都可以引导您通过未知代码的意外路径。取而代之的是,持有对本来应该扩展的类的引用,然后委托给它。这是与Eric…

Java:BigInteger,如何通过OutputStream编写它 - java

我想将BigInteger写入文件。做这个的最好方式是什么。当然,我想从输入流中读取(使用程序,而不是人工)。我必须使用ObjectOutputStream还是有更好的方法?目的是使用尽可能少的字节。谢谢马丁 参考方案 Java序列化(ObjectOutputStream / ObjectInputStream)是将对象序列化为八位字节序列的一种通用方法。但…