— Привет, Амиго!
— Привет, Билаабо!
— Я расскажу тебе сегодня про несколько ключевых слов в 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;
}
}
— Действительно интересная тема, и абсолютно все понятно, спасибо, Билаабо!
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ