Главная » Java » Методы и классы final Java

1

 

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

 

final class NoExtending {

// …

}

 

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

Применение признак а final в объявлениях классов и методов способно повысить уровень безопасности кода. Если класс снабжен модификатором final, никто не в Состоянии расширить класс и, вероятно, нарушить при этом его контракт. Если признаком final обозначен метод, вы можете полностью доверять его внутренней реализации во всех ситуациях, не опасаясь "подделки". Уместно применить final, например, в объявлении метода, предусматривающего проверку пароля, вводимого пользователем, чтобы гарантировать точное Исполнение того, что методом предусмотрено изначально. Возможному злоумышленнику не удастся изменить исходную реализацию такого метода, "подсунув" программе его переопределенную версию, которая, скажем, всегда возвращает значение true, свидетельствующее об успешной регистрации пользователя, независимо от того, какой пароль он ввел на самом деле. Вы вправе, если позволяет конкретная ситуация, пойти дальше и объявить как final класс целиком; метод ValidatePassword приобретёт то же свойство косвенным путём.

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

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

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

system.out.println("id = " + rose.name);

system.out.println("id = " + rose.getName());

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

Та же схема оптимизации может быть применена компилятором и по отношению к методам private и statiс, так как и они не допускают переопределения.

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

Упражнение 3.4. Целесообразно ли включить в объявления методов (и если да, та каких именно) классов vehicle и passengervehicle модификатор final?

Источник: Арнолд, Кен, Гослинг, Джеймс, Холмс, Дэвид. Язык программирования Java. 3-е изд .. : Пер. с англ. – М. : Издательский дом «Вильяме», 2001. – 624 с. : ил. – Парал. тит. англ.

По теме:

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

1 комментарий

  1. Упражнение 3.4. Целесообразно ли включить в объявления методов (и если да, та каких именно) классов vehicle и passengervehicle модификатор final?

    опечатка