При провозглашении свойств, методов и классов в Java, ключевое слово можно использовать для его изменения. Окончательная переменная является постоянной и может быть назначена только один раз; Последний метод не может быть переписан подклассом; Последний класс не может быть унаследован.
1. Окончательные члены
Объявление окончательного поля помогает оптимизатору принимать лучшие решения для оптимизации, потому что, если компилятор знает, что значение поля не изменится, он может безопасно кэшировать значение в регистре. Последнее поле также обеспечивает дополнительный уровень безопасности, заставляя компилятор заставлять поле только для чтения.
1.1 О окончательном назначении участников
1) В Java обычные переменные могут быть инициализированы по умолчанию. Но переменные конечного типа должны быть явно инициализированы.
2) Окончательные члены могут и могут быть инициализированы только один раз.
3) Окончательный член должен быть инициализирован при объявлении (присваивая значение непосредственно конечной переменной, когда она определена) или в конструкторе, и не может быть инициализирован в другом месте.
Пример 1 Bat.java
открытый класс Bat {Final Double Pi = 3,14; // назначить окончательный int i при определении; // Поскольку это должно быть инициализировано в конструкторе, окончательный список <At> список не может быть назначен здесь; // Поскольку это должно быть инициализировано в конструкторе, BAT () не может быть назначен здесь {i = 100; list = new LinkedList <Tat> (); } Bat (int ii, list <bat> l) {i = ii; list = l; } public static void main (string [] args) {bat b = new Bat (); B.List.Add (New Bat ()); // bi = 25; // b.list = new ArrayList <Tat> (); System.out.println ("i =" + bi + "Тип списка:" + b.list.getClass ()); b = новая летучая мышь (23, новый ArrayList <Tat> ()); B.List.Add (New Bat ()); System.out.println ("i =" + bi + "Тип списка:" + b.list.getClass ()); }}
результат:
I = 100 Тип списка: класс java.util.linkedlisti = 23 Тип списка: класс java.util.arraylist
В основном методе есть две строки утверждений, которые прокомментированы. Если вы удалите комментарий, программа не сможет скомпилировать. Это означает, что независимо от того, является ли это значением I или типа списка, после инициализации его нельзя изменить. Однако B может указать значение I или типа списка путем повторной синициализации.
1.2 Неверная инициализация окончательного эталонного поля
Немного неприятно использовать окончательное поле правильно, особенно для ссылок на объекты, конструкторы которых могут сделать исключения. Поскольку конечное поле должно быть инициализировано только один раз в каждом конструкторе, если конструктор, на который ссылается конечный объект, может бросить исключение, компилятор может сообщить об ошибке, в которой говорится, что поле не было инициализировано. Компилятор, как правило, достаточно умный, чтобы обнаружить, что инициализация в каждой ветви двух ветвей кода Mutex (например, если ... иначе блоки) происходит только один раз, но обычно не так «прощают», чтобы попробовать ... ловить блоки.
У следующего кода обычно есть проблемы.
класс Thingie {public statice thinge getDefaultThingie () {return new Thingie (); }} открытый класс foo {private final Thinge Thingie; public foo () {try {thingie = new Thingie (); } catch (Exception e) {thingie = thingie.getDefaultThingie (); // Ошибка: Конечное поле, возможно, уже было назначено}}}
Вы можете изменить это.
открытый класс foo {Private Final Thingie Thingie; public foo () {thingie temptionie; попробуйте {temptionie = new Thingie (); } catch (Exception e) {temptingie = thingie.getDefaultThingie (); } thingie = temptionie; }}
1.3 об использовании окончательного участника
Когда вы определяете переменную в классе, добавьте конечное ключевое слово перед ней, это означает, что после инициализирована эта переменная, ее нельзя изменить. Значение неизменности здесь заключается в том, что его значение неизменно для основного типа, и его ссылка больше не может быть изменена для переменной объекта. Тем не менее, сами объекты могут быть изменены, и Java не предоставляет способ сделать какие -либо объекты постоянными. Это ограничение также подходит в массивах, которые являются объектами.
Пример 2
Приватный окончательный int val_one = 9; частная статическая конечная окончательная финальная int val_two = 99; public static final int val_three = 999;
Поскольку val_one и val_tow являются окончательными примитивными типами со значениями времени компиляции, оба могут использоваться в качестве константы времени компиляции, а существенной разницы нет. Val_three - более типичный способ определения констант: определяется как публичная, его можно использовать вне пакета; определяется как статический, чтобы подчеркнуть только одну копию; определяется как окончательный, чтобы указать, что это постоянное.
Переменная, помеченная конечная, становится постоянной, но эта «постоянная» может использоваться только внутри этого класса и не может использоваться непосредственно за пределами класса. Однако, когда мы используем общественный статический финал, чтобы отметить константу, эта константа становится глобальной константой (поле, которое является одновременно статичным и конечным, занимает только часть места для хранения, которое не может быть изменено). Кроме того, константы, определенные таким образом, могут быть назначены только при определении, и их нельзя использовать в другом месте.
Пример 3
Значение класса {int i; Общественное значение (int i) {this.i = i; / Приватный идентификатор строки; public finaldata (String Id) {this.id = id; } частный финал int i4 = rand.nextint (20); статический финал int i5 = rand.nextint (20); public String toString () {return id + ":" + "i4:" + i4 + ", i5 =" + i5; } public static void main (string [] args) {finalData fd1 = new FinalData ("fd1"); System.out.println (fd1); System.out.println («Создание нового FinalData»); FinalData fd2 = new FinalData ("fd2"); System.out.println (fd1); System.out.println (FD2); }}
результат
FD1: i4: 6, i5 = 3 Creating new FinalDatafd1: i4: 6, i5 = 3fd2: i4: 17, i5 = 3
В разделе «Примеры» показана разница между определением конечного значения как статического (i5) и нестатического (i4). Эта разница появится только тогда, когда значение инициализируется во время выполнения, потому что компилятор в равной степени обрабатывает скомпилированное значение. (И они могут исчезнуть из -за оптимизации.) Вы увидите эту разницу, когда запустите программу. Обратите внимание, что в FD1 и FD2 значение i5 не может быть изменено, создав второй объект FinalData. Это потому, что он статичен, который инициализируется при загрузке, не каждый раз, когда создается новый объект.
Пример 4
Значение класса {int i; Общественное значение (int i) {this.i = i; }} public class… {частное значение v1 = новое значение (11); частное окончательное значение v2 = новое значение (22); частное статическое окончательное значение v3 = новое значение (33); …} Public static void main (string [] args) {… fd1.v2.i ++; // ok-object не постоянный! fd1.v1 = новое значение (9); // ok-не окончательно fd1.v2 = новое значение (0); // Ошибка: не может изменить ссылку на fd1.v3 = новое значение (1); // Ошибка: не может изменить ссылку…} Переменные от V1 до V3 иллюстрируют значение окончательных ссылок. Как вы можете видеть в main (), вы не можете думать, что не можете изменить ее ценность только потому, что V2 является окончательным. Поскольку это ссылка, окончательный означает, что вы не можете снова указать V2 на другой новый объект.
Пример 5
public Class… {private final int [] a = {1,2,3,4,5,6}; …} Public static void main (String [] args) {… for (int i = 0; i <fd1.a.length; i ++) fd1.a [i] ++; // ok-object не постоянный! fd1.a = new int [3]; // Ошибка: не может изменить ссылку…} Наличие того же значения для массива (он может изменить свое значение, но он не может указывать на новый объект), массив - это еще одна ссылка.
1.4 Решите ограничения окончательных массивов
Хотя ссылки на массивы могут быть объявлены окончательными, элементы массива не могут. Это означает, что ни классы, которые раскрывают публичные поля окончательного массива или возвращают ссылки на эти поля с помощью их методов, не являются изменчивыми.
// Не неизбежно - массив штатов может быть изменен с помощью вредоносного // callerpublicclass danguroughstates {private final String [] stasts = new String [] {"alabama", "alaska", "ect"}; public String [] getStates () {return States; }}
Аналогичным образом, хотя ссылка на объект может быть объявлена как конечное поле, объект, который он ссылается, все еще может быть изменчивым. Если вы хотите создать инвариантный объект, используя окончательное поле, вы должны предотвратить ссылки на массивы или изменяемые объекты из «побега» вашего класса. Чтобы сделать это без необходимости неоднократно клонировать массив, простой способ преобразовать массив в список.
// Immutable - возвращает немодифицируемый список вместо Saftestaites {Private Final String [] stasts = new String [] {"alabama", "alaska", "ect"}; Частный окончательный список StatesAsSlist = new AbstractList () {public Object get (int n) {return stass [n]; } public int size () {return stass.length; }}; public List getStates () {return stassAsStist; }}
1.5 об использовании окончательных параметров
Еще одно использование - определить параметр в методе как окончательный. Для переменных основных типов это не имеет какого -либо практической значимости, поскольку переменные основных типов проходят значения при вызове метода, то есть вы можете изменить переменную параметра в методе, не влияя на оператор вызова. Однако для переменных объектов это очень практично, потому что переменные объекта передаются при прохождении. Таким образом, ваша модификация переменных объектов в методе также повлияет на переменные объекта в вызове. Если вам не нужно изменять переменные объекта в качестве параметров в методе, явно использование окончательного для объявления помешает вам непреднамеренно модифицировать и влиять на метод вызова.
1.6 о переменных параметра во внутренних классах
Кроме того, при использовании переменных параметров в методе во внутреннем классе эта переменная параметра должна быть объявлена окончательной, прежде чем ее можно будет использовать.
Пример 6 inclass.java
public class inclass {void innerclass (final String str) {class iClass {iClass () {System.out.println (str); }} IClass IC = new IClass (); } public static void main (string [] args) {inclass inc = new inclass (); Inc.InnerClass ("Hello"); }} 2. Окончательный метод
2.1 Окончательное использование метода
1) Чтобы убедиться, что поведение определенной функции оставалось неизменным во время процесса наследования и не может быть переопределено, можно использовать окончательный метод.
2) Все частные и статические методы в классе, естественно, являются окончательными.
2.2 Окончательные и закрытые ключевые слова
Все частные методы в классе неявно указаны как окончательные. Поскольку частный метод не может быть использован, его нельзя перезаписано.
«Переопределение» будет отображаться только в том случае, если метод является частью интерфейса базового класса. То есть объект должен быть в состоянии преобразовать вверх в его примитивный тип и вызывать тот же метод. Если метод является частным, он не является частью интерфейса базового класса. Это просто какой -то код, скрытый в классе, но с тем же именем. Однако, если публичный, защищенный или метод доступа к пакетам генерируется таким же образом в классе экспорта, метод не будет создавать случай «только с тем же именем», который происходит в базовом классе. На этом этапе вы не переопределили метод, только что сгенерировали новый метод. Поскольку частный метод не может быть затронут и может быть эффективно скрыт, больше ничего не нужно учитывать, за исключением существования организационной структуры класса, которому он принадлежит.
3. Финальный класс
Когда класс определяется как окончательный, класс не может быть унаследован. И поскольку окончательный класс запрещает наследование, все методы в конечном классе неявно определены как окончательные, потому что их нельзя перезаписаны.
Финал используется в классах или методах для предотвращения разбитых связей между методами. Например, предположим, что реализация метода класса X предполагает, что метод M будет работать каким -то образом. Объявление X или M как окончательное предотвратит переопределение M -определения M, в результате чего x работает ненормально. Хотя может быть лучше реализовать X без этих внутренних корреляций, это не всегда возможно, и использование окончательного может предотвратить будущие несовместимые изменения.
PS: разница между окончательным, наконец и завершением