Компилятор java 12.0.1 (все мои тесты здесь выполняются в MS Windows) имеет довольно странное поведение при использовании аргумента -sourcepath в отношении того, что он решает скомпилировать. Самый простой способ объяснить это - привести два примера и привести различия в поведении.
Пример 1:
Исходный файл "A.java"
public class A {
public static void main(String[] args) {
System.out.println("Hello World");
B.myMethod();
}
}
Исходный файл "B.java"
public class B {
public static void myMethod() {
System.out.println("Goodbye!");
}
}
Для компиляции примера 1 мы просто используем следующее:
javac -sourcepath . A.java
Это скомпилирует A.java и B.java и создаст A.class и B.class. Мы ожидаем, что он также скомпилирует B.java, потому что A зависит от него. Теперь подождите секунду или около того и без изменения исходного файла ".java", просто повторите команду компиляции, приведенную выше. Вы обнаружите, что он перекомпилирует A.java, и создается новый класс A.class (с обновленной отметкой времени), но B.class не перекомпилируется. Хорошо, это почти то, что можно ожидать. Теперь давайте сравним это со следующим примером ниже.
Пример 2:
Исходный файл "example2 / A.java"
package example2;
public class A {
public static void main(String[] args) {
System.out.println("Hello World");
B.myMethod();
}
}
Исходный файл "example2 / B.java"
package example2;
public class B {
public static void myMethod() {
System.out.println("Goodbye!");
}
}
Исходные файлы одинаковы, за исключением того, что все перемещено в пакет. Мы хотим скомпилировать два исходных файла, находясь в данный момент в папке «example2». Поэтому мы используем следующую команду:
javac -sourcepath .. A.java
Это снова скомпилирует A.java и B.java и создаст A.class и B.class. Здесь нет проблем, как и раньше. Обратите внимание, что -sourcepath теперь "..", потому что теперь это корневая папка с исходным кодом, когда все в пакете. Теперь подождите секунду или около того и без изменения любого исходного файла, просто повторите команду компиляции выше. Вы обнаружите, что он перекомпилирует ОБА A.java и B.java, и создается новый файл A.class и B.class (с обновленными временными метками).
Обратите внимание на разницу в поведении компиляции при повторном запуске команды javac. Когда -sourcefile был "." и файлы не были в пакете, вторая команда «javac» компилирует только исходный файл, указанный в командной строке. Но когда -sourcefile равен ".." и классы находятся в пакете, вторая команда "javac" ВСЕГДА компилирует все зависимые исходные файлы, независимо от того, нужно ли перекомпилировать неуказанные исходные файлы.
Вопрос в том, почему? Какие аргументы я могу передать в командную строку javac, чтобы остановить пример 2 от безусловной перекомпиляции всех зависимых исходных файлов, если их файлы классов имеют более новую временную метку, чем исходные файлы?