Главная » Java » Объявление методов и классов с ключевым словом final

0

Если метод объявлен с атрибутом final, это означает, что ни один расширенный класс не сможет переопределить данный метод с целью изменить его поведение. Другими словами, данная версия метода является окончательной.

Подобным образом могут объявляться целые классы:

final class NoExtending {

// …

}

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

Имеется два основных довода в пользу объявления методов с атрибутом final. Первый из них — безопасность; каждый, кто пользуется классом, может быть уверен, что его поведение останется неизменным, вне зависимости от объектов, с которыми ему приходится работать.

Окончательные  классы и методы повышают безопасность. Если класс является окончательным, то вы не сможете объявить расширяющий его класс и, следовательно, не сможете нарушить его контракт. Если же окончательным является метод, вы можете положиться на его реализацию (разумеется, лишь в том случае, если в нем не вызываются неокончательные методы). Например, final может использоваться для метода проверки введенного пароля validatePassword, чтобы этот метод всегда выполнял свои

функции и не был переопределен с тем, чтобы при всех обстоятельствах  возвращать true. Кроме того, можно пометить с атрибутом final целый класс, содержащий этот метод, чтобы запретить его расширение и избежать возможных проблем, связанных с реализацией validatePassword.

Во многих случаях уровень безопасности класса, объявленного final, может быть достигнут за счет того, что класс остается расширяемым, а каждый из его методов объявляется final. В этом случае можно быть уверенным в работе данных методов и при этом оставить возможность расширения посредством добавления новых функций без переопределения существующих методов. Разумеется, поля, на которые опираются методы final, должны быть объявлены private, иначе расширенный класс сможет все испортить за счет модификации этих полей.

Класс или метод, помеченный final, серьезно ограничивает использование данного класса. Если метод объявляется final, то вы должны быть действительно уверены в том, что его поведение ни при каких обстоятельствах не должно измениться. Вы ограничиваете гибкость класса, усложняя жизнь другим разработчикам, которые захотят

воспользоваться  вашим классом для повышения функциональности  своих программ. Если класс помечен final, то никто не сможет расширить его, следовательно, его полезность ограничивается. Объявляя что-либо с ключевым словом final, убедитесь в том, что вытекающие из этого ограничения действительно необходимы.

Однако использование final упрощает оптимизацию программы. При вызове метода, не являющегося final, runtime-система Java определяет фактический тип объекта, связывает вызов с нужной реализацией метода для данного типа и затем вызывает данную реализацию. Но если бы, скажем, метод nameOf в классе Attr был объявлен как final и у вас имелась ссылка на объект типа Attr или любого производного от него типа, то при вызове метода можно обойтись и без всех этих действий. В простейшем случае (таком, как nameOf) вызов метода в программе можно заменить телом метода. Такой механизм

известен под названием “встроенных методов” (inlining). Встроенный метод приводит к тому, что следующие два оператора становятся эквивалентными:

System.out.println(“id = ” + rose.name); System.out.println(“id = ” + rose.nameOf());

Хотя эти два оператора приводят к одному результату, применение метода nameOf позволяет сделать поле name доступным только для чтения и предоставляет в ваше распоряжение все преимущества абстрагирования,  позволяя в любой момент изменить реализацию метода.

По отношению к рассматриваемой  оптимизации методы private и static эквивалентны методам final, поскольку они также не могут быть переопределены.

Некоторые проверки для классов final осуществляются быстрее. В сущности, многие из них производятся на стадии компиляции; кроме того, ошибки выявляются быстрее. Если компилятор Java имеет дело со ссылкой на класс вида final, он точно знает тип объекта, на который она указывает. Для таких классов известна вся иерархия, так что компилятор может проверить, все ли с ними в порядке. Для ссылок на объекты, не являющиеся final, многие проверки осуществляются лишь во время выполнения программы.

Упражнение 3.4

Какие из методов классов Vehicle и PassengerVehicle  имеет смысл сделать final (если таковые имеются)?

Источник: Арнольд К., Гослинг Д. – Язык программирования Java (1997)

По теме:

  • Комментарии