— Привіт, Аміго!
— Привіт, Білаабо!
— Я розповім тобі сьогодні про кілька ключових слів у 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 клас.
Зверніть увагу на такий момент — т.к. значення змінної міняти не можна, їй відразу потрібно привласнити початкове значення:
Цей код скомпілюється | Цей код не скомпілюється |
---|---|
|
|
Але, водночас, Java дозволяє перенести ініціалізацію final-змінних класу в конструктор.
Цей код скомпілюється | Цей код не скомпілюється |
---|---|
|
|
Більш того, у різних конструкторах 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;
}
}
— Справді цікава тема, і абсолютно все зрозуміло, дякую, Білаабо!
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ