Ключевое слово final
Часть раздела Объектно-ориентированное программирование путешествия по Java на Coddy — урок 13 из 87.
Ключевое слово final в Java предотвращает изменение. Его можно применять к переменным, методам и классам, и в каждом случае эффект будет разным.
При применении к переменной, final делает её константой — после присвоения её значение не может быть изменено:
public class Circle {
private final double PI = 3.14159;
private final double radius;
public Circle(double radius) {
this.radius = radius; // Можно присвоить один раз в конструкторе
}
public void setRadius(double r) {
// this.radius = r; // Ошибка! Нельзя переназначить final переменную
}
}Переменная final должна быть инициализирована либо при объявлении, либо в конструкторе. После этого любая попытка переназначить её приводит к ошибке компиляции.
Для ссылочных типов final означает, что ссылка не может указывать на другой объект, но содержимое самого объекта все еще может меняться:
private final StringBuilder name = new StringBuilder("John");
// name = new StringBuilder("Jane"); // Ошибка! Нельзя переназначить
name.append(" Doe"); // ОК! Содержимое объекта может менятьсяИспользование final с полями четко передает намерение — оно сообщает другим разработчикам, что это значение никогда не должно меняться после инициализации. Это особенно полезно для конфигурационных значений, идентификаторов или любых данных, которые должны оставаться неизменными на протяжении всего жизненного цикла объекта.
Задание
ЛегкоДавайте создадим систему регистрации Student, которая использует ключевое слово final для защиты данных, которые никогда не должны меняться после регистрации студента.
Вы создадите два файла для организации своего кода:
Student.java: Создайте класс Student, в котором определенная информация навсегда блокируется после установки:- Поле
finalstudentId(String) — присваивается при создании и никогда не может быть изменено - Поле
finalenrollmentYear(int) — год поступления студента, также является постоянным - Обычное приватное поле
name(String) — может быть обновлено, если студент изменит свое имя - Конструктор, который принимает все три значения и инициализирует поля
- Геттер
getStudentId()для ID студента - Геттер
getEnrollmentYear()для года поступления - Геттер
getName()и сеттерsetName()для имени - Метод
getInfo(), который возвращает:"ID: [studentId] | Name: [name] | Enrolled: [enrollmentYear]"
- Поле
Main.java: Создайте объект Student, затем обновите его имя и выведите информацию о нем. Вы получите четыре входных значения: ID студента, начальное имя, год поступления и новое имя для обновления. Выведите две строки:- Информацию о студенте до изменения имени
- Информацию о студенте после изменения имени
Вы получите четыре входных значения по порядку: studentId (String), name (String), enrollmentYear (int) и newName (String).
Обратите внимание, как поля final защищают ID и год поступления студента — это постоянные записи, которые не должны меняться, в то время как имя можно обновить через его сеттер.
Шпаргалка
Ключевое слово final предотвращает изменение в Java. Оно может применяться к переменным, методам и классам.
При применении к переменной, final делает её константой — после присвоения её значение не может быть изменено:
public class Circle {
private final double PI = 3.14159;
private final double radius;
public Circle(double radius) {
this.radius = radius; // Можно присвоить один раз в конструкторе
}
public void setRadius(double r) {
// this.radius = r; // Ошибка! Невозможно переназначить переменную final
}
}Переменная final должна быть инициализирована либо при объявлении, либо в конструкторе. После этого любая попытка переназначить её вызывает ошибку компиляции.
Для ссылочных типов final означает, что ссылка не может указывать на другой объект, но содержимое объекта всё равно может меняться:
private final StringBuilder name = new StringBuilder("John");
// name = new StringBuilder("Jane"); // Ошибка! Невозможно переназначить
name.append(" Doe"); // OK! Содержимое объекта может менятьсяИспользование final с полями передает намерение — оно указывает на то, что значение никогда не должно меняться после инициализации, что полезно для конфигурационных значений, идентификаторов или константных данных.
Попробуйте сами
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Чтение входных данных
String studentId = scanner.nextLine();
String name = scanner.nextLine();
int enrollmentYear = scanner.nextInt();
scanner.nextLine(); // поглощение символа новой строки
String newName = scanner.nextLine();
// TODO: Создайте объект Student с начальными значениями
// TODO: Выведите информацию о студенте до изменения имени
// TODO: Обновите имя студента, используя setter
// TODO: Выведите информацию о студенте после изменения имени
}
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыВведение в ООПКлассы и объектыКлючевое слово thisМетодыПоля (атрибуты)Метод-конструкторПерегрузка конструкторовИтоги — Простой калькулятор4Наследование
Основы наследования (extends)Ключевое слово superПереопределение методов (@Override)Цепочка конструкторовКласс ObjectОдиночное и многоуровневое наследованиеПочему нет множественного наследования классовИтоги — Иерархия сотрудников7Специальные методы и класс Object
Метод toString()equals() и hashCode()Метод clone()compareTo() и ComparableИнтерфейс ComparatorПовторение — Кастомная сортировка2Модификаторы доступа и инкапсуляция
Обзор уровней доступаМетоды геттеры и сеттерыСокрытие данныхКлючевое слово finalИтоги — Менеджер банковского счета5Полиморфизм
Основы перегрузки методовПереопределение методов (Run-Time)Upcasting и DowncastingОператор instanceofАбстрактные классы и методыИтоги: Калькулятор фигур8Продвинутые концепции ООП
Композиция против наследованияАгрегация против композицииВнутренние, вложенные и анонимные классыEnums и методы перечисленийRecords (Java 16+)Sealed-классы (Java 17+)11Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн BuilderПаттерн ObserverПаттерн Strategy3Свойства класса и статические члены
Переменные экземпляра и статические переменныеСтатические методыСтатические блокиКонстанты (static final)Итоги: Счетчик и утилиты6Интерфейсы и абстрактные классы
Введение в интерфейсыРеализация интерфейсовРеализация нескольких интерфейсовDefault и Static методы в интерфейсахАбстрактные классы vs ИнтерфейсыФункциональные интерфейсыИтоги — Платежная система9Обобщения
Введение в обобщенияОбобщенные классыОбобщенные методыОграниченные параметры типаСимволы подстановки (Wildcards: ?, extends, super)Итоги — Обобщенный контейнер12Паттерны проектирования. Часть 2
Паттерн «Команда»Паттерн «Адаптер»Паттерн «Декоратор»Паттерн «Шаблонный метод»Паттерн «Состояние»Паттерн «Компоновщик»Паттерн «Итератор»