Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
GoslingJava2.doc
Скачиваний:
139
Добавлен:
23.02.2016
Размер:
2.39 Mб
Скачать

3.4.1. Ключевое слово super

Ключевое слово super может использоваться во всех нестатических методах класса. При доступе к полям или вызове методов ключевое слово super представляет собой ссылку на текущий объект как экземпляр суперкласса. Использование super оказывается единственным случаем, при котором выбор реализации метода зависит от типа ссылки. В вызове вида super.method всегда используется реализация method из суперкласса, а не его переопределенная реализация, которая находится где-то ниже в иерархии классов.

Вызов методов с помощью ключевого слова super отличается от любых других ссылок, в которых метод выбирается в зависимости от фактического типа объекта, а не типа ссылки. При вызове метода через ссылку super вы обращаетесь к реализации метода, основанной на типе суперкласса. Приведем пример практического использования super:

class That {

/** вернуть имя класса */

protected String nm() {

return “That”;

}

}

class More extends That {

protected String nm() {

return “More”;

}

protected void printNM() {

That sref = super;

System.out.println(“this.nm() = ” + this.nm());

System.out.println(“sref.nm() = ” + sref.nm());

System.out.println(“super.nm() = ” + super.nm());

}

}

А вот как выглядит результат работы printNM:

this.nm() = More

sref.nm() = More

super.nm() = That

Ключевое слово super может также применяться для доступа к защищенным членам суперкласса.

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

Если метод объявлен с атрибутом 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 (если таковые имеются)?

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]