Нам нужно выделить два аспекта констант:
- имена для значений, известных во время разработки, которые мы вводим для лучшей ремонтопригодности, и
- значения, доступные для компилятора.
И затем есть связанный третий тип: переменные, значение которых не изменяется, то есть имена для значения. Разница между этими неизменяемыми переменными и константой заключается в том, что значение определяется / присваивается / инициализируется: переменная инициализируется во время выполнения, но значение константы известно во время разработки. Это различие немного мутное, так как значение может быть известно во время разработки, но фактически создается только во время инициализации.
Но если значение константы известно во время компиляции, то компилятор может выполнять вычисления с этим значением. Например, язык Java имеет концепцию константных выражений . Константное выражение - это любое выражение, состоящее только из литералов примитивов или строк, операций с константными выражениями (таких как приведение, сложение, конкатенация строк) и константных переменных. [ JLS §15.28 ] Постоянная переменная - это finalпеременная, которая инициализируется постоянным выражением. [JLS §4.12.4] Итак, для Java это константа времени компиляции:
public static final int X = 7;
Это становится интересным, когда постоянная переменная используется в нескольких единицах компиляции, а затем объявление изменяется. Рассмотреть возможность:
Теперь, когда мы скомпилируем эти файлы, B.classбайт-код объявит поле, Y = 9потому что B.Yэто постоянная переменная.
Но когда мы A.Xизменяем переменную на другое значение (скажем, X = 0) и перекомпилируем только A.javaфайл, тогда B.Yвсе равно ссылается на старое значение. Это состояние A.X = 0, B.Y = 9несовместимо с объявлениями в исходном коде. Удачной отладки!
Это не значит, что константы никогда не должны изменяться. Константы определенно лучше магических чисел, которые появляются без объяснения в исходном коде. Тем не менее, значение общественных констант является частью вашего общественного API . Это не относится к Java, но также встречается в C ++ и других языках, которые имеют отдельные модули компиляции. Если вы измените эти значения, вам нужно будет перекомпилировать весь зависимый код, т.е. выполнить чистую компиляцию.
В зависимости от природы констант, они могли привести к неверным предположениям разработчиков. Если эти значения изменены, они могут вызвать ошибку. Например, набор констант может быть выбран так, чтобы они формировали определенные битовые комбинации, например public static final int R = 4, W = 2, X = 1. Если они изменены, чтобы сформировать другую структуру, как R = 0, W = 1, X = 2тогда, существующий код, такой как, boolean canRead = perms & Rстановится неправильным. И просто подумайте о том, что веселье должно было Integer.MAX_VALUEизмениться! Здесь нет никакого исправления, просто важно помнить, что значение некоторых констант действительно важно и не может быть изменено просто.
Но для большинства констант их изменение будет нормальным, если учесть вышеупомянутые ограничения. Константу безопасно менять, когда важно значение, а не конкретное значение. Это, например, относится к настраиваемым элементам, таким как BORDER_WIDTH = 2или, TIMEOUT = 60; // secondsили шаблонам, таким как, API_ENDPOINT = "https://api.example.com/v2/"хотя, возможно, некоторые или все из них должны быть указаны в файлах конфигурации, а не в коде.