Я обнаружил ошибку в компиляторе 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 всегда должен компилироваться перед классом 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
Ошибка компиляции, когда она возникает, всегда является то же самое - метод запуска в экземплярах перечисления Действия не может быть найден, даже если все они реализуют интерфейс, имеющий этот метод выполнения.
Program.java:6: cannot find symbol
symbol : method run(java.lang.String)
location: class problem.Actions
Actions.SKIP.run("hello");
Похоже, ошибка связана с , о которой сообщалось на сайте Oracle . Я использую javac 1.6.0_29 в Mac OS X 10.7.2 x86_64, но также воспроизвел его в Linux.
Эта проблема стала очевидной, когда я использую Maven для сборки и, похоже, не могу контролировать порядок компиляции. Поэтому я ищу обходной путь, чтобы заставить maven компилировать файлы в таком порядке, чтобы избежать этой ошибки компилятора, или возиться с флагами компилятора (или что-то в этом роде), чтобы избежать этого.Проблема возникает как на рабочих станциях, так и в средах непрерывной интеграции, поэтому она должна работать повсеместно. Есть предложения?
РЕДАКТИРОВАТЬ: Просто попробовал следующий обходной путь, который, несмотря на простое присвоение рассматриваемого перечисления переменной с типом реализуемого интерфейса, неожиданно приводит к исчезновению ошибки.
public class Program {
public static void main(String[] args) {
ActionSpec a = Actions.SKIP;
a.run("hello");
}
}
Все еще интересуются мнениями других.