Компилятор подставляет значение константы времени компиляции во все выражения, где оно используется; таким образом предотвращаются некоторые издержки выполнения. В Java подобные константы должны относиться к примитивным типам, а для их определения используется ключевое слово final. Значение такой константы присваивается во время определения.
Поле, одновременно объявленное с ключевыми словами static и final, существует в памяти в единственном экземпляре и не может быть изменено.
При использовании слова final со ссылками на объекты его смысл не столь очевиден. Для примитивов final делает постоянным
Следующий пример демонстрирует использование final для полей классов:
// reusing/Final Data java
// Действие ключевого слова final для полей.
import java util *,
import static net mindview.util Print.*;
class Value {
int i. // доступ в пределах пакета public Value(int i) { this i = i, }
}
public class FinalData {
private static Random rand = new Random(47); private String id,
public FinalData(String id) { this.id = id: } // Могут быть константами времени компиляции, private final int valueOne = 9. private static final int VALUE_TW0 = 99, // Типичная открытая константа, public static final int VALUE_THREE = 39: // He может быть константой времени компиляции: private final int i4 = rand.nextlnt(20); static final int INT_5 = rand nextlnt(20); private Value vl = new Value(ll): private final Value v2 = new Value(22), private static final Value VAL_3 = new Value(33): // Массивы.
private final int[] a = { 1. 2, 3. 4, 5, 6 }: public String toStringO {
return id + ": " + "i4 = " + i4 + ". INT_5 = " + INT_5;
}
public static void main(String[] args) {
FinalData fdl = new FinalDataCfdl"),
//! fdl.valueOne++, // Ошибка значение нельзя изменить
fdl.v2 i++, // Объект не является неизменным!
fdl.vl = new Value(9); // OK - не является неизменным
for(int i = 0, i < fdl.a.length; i++)
fdl a[i]++; // Объект не является неизменным! //! fdl v2 = new Value(O); // Ошибка: ссылку //! fdl VAL_3 = new Valued); // нельзя изменить //' fdl a = new int[3], print(fdl),
print("Создаем FinalData"); FinalData fd2 = new FinalData("fd2M). print(fdl), print(fd2):
}
} /* Output.
fdl i4 = 15. INT 5 = 18 Л
Создаем Final Data fdl: i4 = 15. INT_5 = 18 fd2: i4 = 13. INT_5 = 18 *///:-
Так как valueOne и VALUE_TWO являются примитивными типами со значениями, заданными на стадии компиляции, они оба могут использоваться в качестве констант времени компиляции, и принципиальных различий между ними нет. Константа VALUE_THREE демонстрирует общепринятый способ определения подобных полей: спецификатор public открывает к ней доступ за пределами пакета; ключевое слово static указывает, что она существует в единственном числе, а ключевое слово final указывает, что ее значение остается неизменным. Заметьте, что примитивы final static с неизменными начальными значениями (то есть константы времени компиляции) записываются целиком заглавными буквами, а слова разделяются подчеркиванием (эта схема записи констант позаимствована из языка С).
Само по себе присутствие final еще не означает, что значение переменной известно уже на стадии компиляции. Данный факт продемонстрирован на примере инициализации i4 и INT_5 с использованием случайных чисел. Эта часть программы также показывает разницу между статическими и нестатическими константами. Она проявляется только при инициализации во время исполнения, так как все величины времени компиляции обрабатываются компилятором одинаково (и обычно просто устраняются с целью оптимизации). Различие проявляется в результатах запуска программы. Заметьте, что значения поля i4 для объектов fdl и fd2 уникальны, но значение поля INT_5 не изменяется при создании второго объекта FinalData. Дело в том, что поле INT_5 объявлено как static, поэтому оно инициализируется только один раз во время загрузки класса.
Переменные от vl до VAL_3 поясняют смысл объявления ссылок с ключевым словом final. Как видно из метода main(), объявление ссылки v2 как final еще не означает, что ее объект неизменен. Однако присоединить ссылку v2 к новому объекту не получится, как раз из-за того, что она была объявлена как final. Именно такой смысл имеет ключевое слово final по отношению к ссылкам. Вы также можете убедиться, что это верно и для массивов, которые являются просто другой разновидностью ссылки. Пожалуй, для ссылок ключевое слово final обладает меньшей практической ценностью, чем для примитивов.
Пустые константы