Ваша гипотеза почти верна.Это не просто final
переменные, а так называемые " постоянные переменные ":
Мы называем переменную примитивного типа или типа String, которая является окончательной и инициализируется с помощьюпостоянное выражение времени компиляции ( §15.28 ) постоянная переменная.Независимо от того, является ли переменная постоянной или нет, это может иметь значение в отношении инициализации класса ( §12.4.1 ), двоичной совместимости ( §13.1 , §13.4.9 ) и определенного присвоения ( §16 ).
Затем в разделе о двоичной совместимости (§13.1) :
Ссылки на поля, которые являются постоянными переменными (§4.12.4), разрешаются во время компиляции в постоянное значение, которое обозначается.Никакая ссылка на такое поле констант не должна присутствовать в коде в двоичном файле (кроме класса или интерфейса, содержащего поле констант, в котором будет код для его инициализации)
и ( §13.4.9 ) (мой акцент):
Если поле является константной переменной (§4.12.4), то удаляется ключевое слово final или изменяется его значение не нарушит совместимость с уже существующими двоичными файлами, заставив их не работать, но они не увидят никаких новых значений для использования поля, если они не будут перекомпилированы .
В предыдущей работе мы использовали это для создания своего рода системы условной компиляции, чтобы мы могли создавать производственные двоичные файлы со всеми удаленными операторами отладки.
Когда вы комбинируете это с тем, какjavac
задача определяет, какие классы для перекомпиляции вы получаете поведение, которое вы видите:
Только файлы Java, которые не имеют соответствующего файла .class или гдеФайл классов старше, чем файл .java, который будет скомпилирован.
Примечание. Apache Ant использует только имена исходных файлов и файлов классов, чтобы найти классы, которые необходимо перестроить.Он не будет сканировать исходный код и, следовательно, не будет знать о вложенных классах, классах, имена которых отличаются от исходного файла, и так далее.См. Задачу <depend>
для проверки зависимостей, основанных не только на времени существования / изменения.
Самый простой способ исправить это - чистая полная компиляция каждый разс чем-то вроде ant clean compile
(при условии, что у вас есть цель clean
, которая удаляет все ваши файлы классов).Хотя это может быть слишком медленно.
Я также собирался предложить вам посмотреть на задачу depend
, как предложено в документации для задачи javac
, но, глядя наДокументы для него (я сам на самом деле не использовал его), похоже, это не поможет (см. раздел «Ограничения»):
Наиболее очевидный пример этих ограничений заключается в том, чтозадача не может сказать, какие классы перекомпилировать при изменении константного примитивного типа данных, экспортируемого другими классами.
Один из возможных способов, если вы обнаружите, что чистая компиляция выполняется каждый раз слишком медленно, будетчтобы значения в вашем классе GUIConstants
не были постоянными, по крайней мере, пока вы вносите изменения.Вы можете сделать значения не окончательными, закомментировав все ключевые слова final
, тогда другие классы должны увидеть ваши изменения.Когда вы будете довольны новыми значениями, вставьте обратно final
и перекомпилируйте (и, конечно же, убедитесь, что все работает правильно).