JavaRush /Курсы /Java Multithreading /final и другие ключевые слова java

final и другие ключевые слова java

Java Multithreading
3 уровень , 1 лекция
Открыта
final и другие ключевые слова java - 1

— Привет, Амиго!

— Привет, Билаабо!

— Я расскажу тебе сегодня про несколько ключевых слов в Java. Но начну с самого интересного – ключевого слова final. Если перевести его с английского, то получится что-то вроде финальный или окончательный.

Ключевое слово final можно добавлять при объявлении переменной, метода и класса.

— А зачем нужен этот final?

— Все довольно просто. Если мы пометили переменную словом final, то она становится неизменной:

final int i = 5;
i++; //ошибка компиляции – нельзя менять значение переменной i

— Ясно.

— Если мы пометили метод словом final, то этот метод запрещено переопределять в классах-наследниках:

class Cat
{
 public final String getName()
 {
  return "cat";
 }
}

class Tiger extends Cat
{
 public String getName() //ошибка компиляции – нельзя переопределять метод getName()
 {
  return "tiger";
 }
}

— Ясно. А зачем может понадобиться запрещать переопределение метода?

— Например, программист написал в этом методе много важного кода и хочет, чтобы все наследники его класса гарантированно имели заданное поведение.

И наконец – третье.

Если мы пометим словом final класс, то таким образом мы запретим наследоваться от него.

public final class Cat
{
 public String getName()
 {
  return "cat";
 }
}

class Tiger extends Cat //ошибка компиляции – нельзя наследоваться от класса Cat
{
 public String getName() 
 {
  return "tiger";
 }
}

— А зачем запрещать наследование классов?

— Ты должен понять, что запрет наследования идет не из вредности, а ради безопасности и целостности кода. Если наследование класса не запрещено, то подразумевается, что оно разрешено. И код проектировщика класса будет нормально работать и с объектами его класса и с объектами класса-наследника.

А вот если разработчик видит, что даже при небольших изменениях в его классе, все перестанет работать, как задумано, тогда ему лучше запретить наследование.

— Класс String, например, объявлен как final, как и все примитивные типы: Integer, Boolean, Double, Character,…

— Ага, понимаю. Класс String сделан immutable и если бы вдруг появились изменяемые строки, то много чего перестало бы работать.

— Ну, почти. Скажем так, все работало бы почти по-старому, но иногда возникали бы ошибки, которые было бы очень сложно найти и понять. Поэтому, в некоторых случаях наследование классов или методов не грех и запретить – меньше потом ошибок вылавливать.

— А где еще можно писать final?

— final можно писать перед переменными-аргументами функции и перед переменными в методе. Вот пример:

public void setName(final String name)
{
 final String displayName = "Mr."+name;
  …
 this.name = displayName;
}

— А какой в этом смысл?

— Ну, смыслов – два. Во-первых, мы объявляем переменную final – если хотим сообщить другим разработчикам, что это значение – определенная константа, а не просто переменная.

Например, мы хотим рассчитать НДС от цены:

public int getPriceNDS()
{
 final int NDS = 20;
 return this.price * NDS / 200;
}

И во-вторых, если мы будем писать локальные или анонимные внутренние классы, то такие переменные нам понадобятся. Я расскажу о таких классах в ближайшее время. Но не сегодня.

— Ок, пока вроде ничего сложного.

— Обрати внимание, что неизменяемой становится только переменная, а не объект, на который она ссылается. Объект можно менять еще как.

— Как раз хотел уточнить этот момент. А нет способа сделать объект неизменным?

— Нет, только если ты напишешь immutable класс.

Обрати внимание на такой момент — т.к. значение переменной менять нельзя, то ей сразу нужно присвоить начальное значение:

Этот код скомпилируется Этот код не скомпилируется
class Home
{
 private final int width = 200;
 private final int height = 100;

 public Home()
 {
 }
}
class Home
{
 private final int width; private final int height;

 public Home()
 {
 }
}

Но, вместе с тем, Java разрешает перенести инициализацию final-переменных класса в конструктор.

Этот код скомпилируется Этот код не скомпилируется
class Home
{
 private final int width = 200;
 private final int height;

 public Home()
 {
  height = 100;
 }
}
class Home
{
 private final int width;
 private final int height;

 public Home()
 {
  height = 100;
 }
}

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

Этот код скомпилируется
class Home
{
 private final int width;
 private final int height;

 public Home()
 {
  height = 100; width = 200;
 }

 public Home(int width)
 {
 this.height = 300; this.width = width;
 }

 public Home(int width, int height)
 {
 this.height = height; this.width = width;
 }
}

— Действительно интересная тема, и абсолютно все понятно, спасибо, Билаабо!

Комментарии (66)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Zim4ik Уровень 51
8 июля 2025
Класс String, например, объявлен как final, как и все примитивные типы: Integer, Boolean, Double, Character Примитивные типы (например, int, double, boolean) — это не классы вообще. Они — встроенные типы языка Java, и не имеют модификаторов вроде final. Но для них существуют классы-обёртки, и вот они-то — final.
Anemon Уровень 13 Expert
25 ноября 2024
Всегда было интересно, в чем именно различие.
SomeBody098 Уровень 51
20 июля 2024
познавательно )
Dmitro Уровень 51
13 июля 2024
В примере с НДС ошибка. Делить нужно на 120, а не на 200: this.price * NDS / 120
Максим Li Уровень 40
19 мая 2024
19.05.2024
Long_byte Уровень 43
13 мая 2024
почему я всегда читаю Билаабо как Билбао
Anonymous #3390940 Уровень 38
13 марта 2024
🦝
Алексей Уровень 40 Expert
10 января 2024
Хорошая леция все по делу
Lo Уровень 35 Expert
23 ноября 2023
В последнем примере в конструкторе поменяли расстановку в аргументах конструктора, а разве так можно делать? Вроде говорили,что как в параметрах так и инициализируем по порядку. Или это уже не важно стало в новой версии ? лекция то вроде не новая...
Rolik Уровень 41
11 апреля 2023
Не раскрыта разница между константами и final переменными. Имя константы в верхнем регистре - общепринятая условность, но не обязательное правило.