【发布时间】:2012-02-29 20:09:33
【问题描述】:
我在 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");
}
}
仍然对别人的意见感兴趣。
【问题讨论】:
-
随着
ActionSpec的引入,它开始工作也就不足为奇了。也许该错误仅限于枚举及其实现的内容。import也可能有帮助。 -
您是否尝试过在枚举中添加
public abstract int run(String d);方法? -
应该不需要,因为枚举类实现了接口,并且它的所有实例都包含方法的实现(否则枚举不会编译)。
-
它适用于 Ubuntu 上的 OpenJDK 1.6.0_23。