58

58


При использовании слова final со ссылками на объекты его смысл не столь очевиден. Для примитивов final делает постояннымзначение, но для ссылки на объект постоянной становитсяссылка.После того как такая ссылка будет связана с объектом, она уже не сможет указывать на другой объект. Впрочем, сам объект при этом может изменяться; в Java нет механизмов, позволяющих сделать произвольный объект неизменным. (Впрочем, вы сами можете напи­сать ваш класс так, чтобы его объекты факически были константными.) Данное ограничение относится и к массивам, которые тоже являются объектами.

Следующий пример демонстрирует использование 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("fd2
M
). 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 обладает меньшей практической ценностью, чем для примитивов.

Пустые константы

В Java разрешается создаватьпустые константы —поля, объявленные как final, которым, однако, не было присвоено начальное значение. Во всех случаях пустую константуобязательнонужно инициализировать перед использовани­ем, и компилятор следит за этим. Впрочем, пустые константы расширяют сво­боду действий при использовании ключевого слова final, так как, например, поле final в классе может быть разным для каждого объекта, и при этом оно со­храняет свою неизменность. Пример:

//: c06:BlankFinal .java // "Пустые" неизменные поля.

class Poppet {

private int i:

Poppet(int ii) { i = ii; }

}

public class BlankFinal {

private final int i = 0; // Инициализированная константа private final int j; // Пустая константа private final Poppet p; // Пустая константа-ссылка II Пустые константы НЕОБХОДИМО инициализировать // в конструкторе: public BlankFinalО {

j = 1; // Инициализация пустой константы р = new Poppet(l); // Инициализация пустой неизменной ссылки

}

public BlankFinal(int х) {

j = х; // Инициализация пустой константы р = new Poppet(x), // Инициализация пустой неизменной ссылки

}

public static void main(String[] args) { new BlankFinal О; new BlankFinal(47),

}

} ///:-

Значения неизменных (final) переменных обязательно должны присваивать­ся или в выражении, записываемом в точке определения переменной, или в ка­ждом из конструкторов класса. Тем самым гарантируется инициализация по­лей, объявленных как final, перед их использованием.

Неизменные аргументы

Java позволяет вам объявлять неизменными аргументы метода, объявляя их с ключевым словом final в списке аргументов. Это значит, что метод не может изменить значение, на которое указывает передаваемая ссылка:

Report Page