АБОБА. Справочник по программированию на Java Методическое пособие
Скачать 242.41 Kb.
|
Использование ключевого слова final для предотвращения переопределенияХотя переопределение методов – одно из наиболее мощных средств Java, в некоторых случаях его желательно избежать. Чтобы запретить переопределение метода, в начале его объявления необходимо указать ключевое слово final. Методы, объявленные как final, переопределяться не могут. Следующий фрагмент кода иллюстрирует это применениеключевого слова final. class A { final void meth() { System.out.println("Это метод final."); } } class B extends A { void meth() { // ОШИБКА! Этот метод не может быть переопределен. System.out.println("Не допускается!"); } } Поскольку метод meth() объявлен как final, он не может быть переопределен в классе B. Попытка выполнить это переопределение приведет к ошибке времени компиляции. Иногда методы, объявленные как final, могут способствовать увеличению производительности программы. Компилятор вправе вставлять вызовы этих методов непосредственно в строку, поскольку он “знает”, что они не будут переопределены подклассом. Часто при вызове небольшого метода типа final компилятор Java может копировать байт-код подпрограммы непосредственно в строку скомпилированного кода вызывающего метода, тем самым снижая значительные накладные расходы системных ресурсов, связанные с вызовом метода. Помещение методов типа final в строку вызывающего кода – лишь потенциальная возможность. Обычно Java разрешает вызовы методов динамически, во время выполнения. Такой подход называют поздним связыванием. Однако поскольку методы типа final не могут переопределяться, обращение к такому методу может быть разрешено во время компиляции. Этот подход называют ранним связыванием. Использование ключевого слова final для предотвращения наследованияИногда будет требоваться предотвратить наследование класса. Для этого в начале объявления класса необходимо поместить ключевое слово final. Объявление класса как final неявным образом объявляет все его методы также как final. Как легко догадаться, одновременное объявление класса как abstract и как final недопустимо, поскольку абстрактный класс принципиально является незавершенным и только его подклассы предоставляют полную реализацию методов. Ниже приведен пример класса типа final. final class A { // ... } // Следующий класс недопустим. class B extends A { // ОШИБКА! Класс A не может иметь подклассы. // ... } Как видно из комментария, класс B не может наследовать от класса A, поскольку A объявлен как final. Класс ObjectВ Java определен один специальный класс – Object. Все остальные классы являются подклассами этого класса. То есть Object – суперкласс всех остальных классов. Это означает, что ссылочная переменная типа Object может ссылаться на объект любого другого класса. Кроме того, поскольку массивы реализованы в виде классов, переменная типа Object может ссылаться также на любой массив. Класс Object определяет методы, которые доступны в любом объекте. Методы getClass(), notify(), notifyAll() и wait() объявлены как final. Остальные методы можно переопределять. Обратите внимание на два метода: equals() и toString(). Метод equals() сравнивает содержимое двух объектов. Если объекты эквивалентны, он возвращает значение true, если нет – false. Точное определение равенства зависит от типа сравниваемых объектов. Метод toString() возвращает строку, которая содержит описание объекта, по отношению к которому он вызван. Кроме того, этот метод автоматически вызывается при выводе объекта с помощью метода println(). Многие классы переопределяют этот метод. Это позволяет им приспосабливать описание специально для создаваемых ими объектных типов. Object clone(): Создает новый объект, не отличающийся от клонируемого объекта boolean equals(Object object): Определяет, равен ли один объект другому void finalize(): Вызывается перед удалением неиспользуемого объекта Class getClass(): Получает класс объекта во время выполнения int hashCode(): Возвращает хеш-код, связанный с вызывающим объектом void notify(): Возобновляет выполнение потока, который ожидает вызывающего объекта void notifyAll(): Возобновляет выполнение всех потоков, которые ожидают вызывающего объекта String toString(): Возвращает строку, которая описывает объект void wait(), void wait(long milliseconds), void wait(long milliseconds int nanoseconds): Ожидает другого потока выполнения |