Изменить стиль страницы

Помимо рассмотренных ранее примеров использования, ключевое слово final можно применять и к переменным экземпляра. Подобным способом создаются именованные константы. Если имени переменной предшествует модификатор final, то значение этой переменной не может быть изменено на протяжении всего времени выполнения программы. Очевидно, что подобным переменным нужно присваивать начальные значения. В главе 6 был рассмотрен простой класс ErrorMsg для обработки ошибок. В нем устанавливается соответствие между кодами ошибок и символьными строками сообщений об ошибках. Ниже приведен усовершенствованный вариант этого класса, в котором для создания именованных констант применяется модификатор final. Теперь, вместо того чтобы передавать методу getErrorMsg () числовое значение, например 2, достаточно указать при его вызове именованную целочисленную константу DISKERR.// Возврат объекта типа String,class ErrorMsg { // Коды ошибок. // Константы объявляются с помощью ключевого слова final. final int OUTERR = 0; final int INERR = 1; final int DISKERR = 2; final int INDEXERR = 3; String msgs[] = { "Output Error", "Input Error", "Disk Full", "Index Out-Of-Bounds" }; // возвратить сообщение об ошибке String getErrorMsg(int i) { if(i >=0 & i < msgs.length) return msgs[i]; else return "Invalid Error Code"; }}class FinalD { public static void main(String args[]) { ErrorMsg err = new ErrorMsg(); // При вызове метода используются константы, // объявленные с помощью ключевого слова final. System.out.println(err.getErrorMsg(err.OUTERR)); System.out.println(err.getErrorMsg(err.DISKERR)); }}

Обратите внимание на то, как используются константы в методе main (). Они являются членами класса ErrorMsg, и поэтому для доступа к ним требуется ссылка на объект этого класса. Разумеется, константы могут быть унаследованы подклассами и непосредственно доступными в них.

Многие программирующие на Java пользуются именами констант типа final, составленными полностью из прописных букв, как в предыдущем примере. Но это не строгое правило, а только принятый стиль программирования.Класс Object

В Java определен специальный класс Object. По умолчанию он считается суперклассом всех остальных классов. Иными словами, все классы являются подклассами, производными от класса Object. Это означает, что переменная ссылки на объект типа Object может ссылаться на объект любого класса. Более того, переменная ссылки на объект типа Object может также ссылаться на любой массив, поскольку массивы реализованы в виде классов.

В классе Object определены перечисленные ниже методы, доступные в любом объекте.МетодНазначениеObject clone ()Создает новый объект, аналогичный клонируемому объектуboolean equals (Object объект)Определяет равнозначность объектовvoid finalize ()Вызывается перед тем, как неиспользуемый объект будет удален системой "сборки мусора"Class<?> getClass()Определяет класс объекта во время выполненияint hashCode ()Возвращает хеш-код, связанный с вызывающим объектомvoid notify()Возобновляет работу потока, ожидающего уведомления от вызывающего объектаvoid notifyAll()Возобновляет работу всех потоков, ожидающих уведомления от вызывающего объектаString toString()Возвращает символьную строку, описывающую объектvoid wait ()Ожидает исполнения другого потокаvoid wait (long миллисекунды)Ожидает исполнения другого потокаvoid wait (long миллисекунды, int наносекунды)Ожидает исполнения другого потока

Методы getClass(), notify(), notifyAll() и wait() объявлены как final,а остальные методы можно переопределять в подклассах. Некоторые из этих методов будут описаны далее в этой книге. Два из них — equals () и toString () — заслуживают особого внимания. Метод equals () сравнивает два объекта. Если объекты равнозначны, то он возвращает логическое значение true, иначе — логическое значение false. Метод toString () возвращает символьную строку, содержащую описание того объекта, которому принадлежит этот метод. Он автоматически вызывается в том случае, если объект передается методу println() в качестве параметра. Во многих классах этот метод переопределяется. В этом случае описание специально подбирается для конкретных типов объектов, которые в них создаются.

Обратите внимание на необычный синтаксис, описывающий значение, возвращаемое методом getClass (). Это обобщенный тип. С помощью обобщений в Java можно указывать в качестве параметра тип данных, используемый в классе или методе. Более подробно обобщения рассматриваются в главе 13.Упражнение для самопроверки по материалу главы 7

Имеет ли суперкласс доступ к членам подкласса? Имеет ли подкласс доступ к членам суперкласса?

Создайте подкласс Circle, производный от класса TwoDShape. В нем должен быть определен метод area (), вычисляющий площадь круга, а также конструктор с ключевым словом super для инициализации членов, унаследованных от класса TwoDShape.

Как предотвратить обращение к членам суперкласса из подкласса?

Опишите назначение и два варианта использования ключевого слова super.

Допустим, имеется следующая иерархия классов:class Alpha { ...class Beta extends Alpha { ...Class Gamma extends Beta { ...В каком порядке вызываются конструкторы этих классов при создании объекта класса Gamma?

Переменная ссылки на суперкласс может указывать на объект подкласса. Объясните, почему это важно и как это связано с переопределением методов?

Что такое абстрактный класс?

Как предотвратить переопределение метода? И как предотвратить наследование класса?

Объясните, каким образом механизмы наследования, переопределения методов и абстрактные классы используются для поддержки полиморфизма.

Какой класс является суперклассом всех остальных классов?

Класс, который содержит хотя бы один абстрактный метод, должен быть объявлен абстрактным. Верно или не верно?

Какое ключевое слово следует использовать для создания именованной константы?

Глава 8 Пакеты и интерфейсы

Основные навыки и понятия

Применение пакетов

Влияние пакетов на доступ к членам класса

Применение модификатора доступа protected

Импорт пакетов

Представление о стандартных пакетах Java

Основные положения об интерфейсах

Реализация интерфейсов

Применение интерфейсных ссылок

Представление о переменных интерфейса

Наследование интерфейсов

Эта глава посвящена рассмотрению двух очень важных, передовых языковых средств Java: пакетов и интерфейсов. Пакет — это группа логически связанных классов. Пакеты помогают лучше организовать код и обеспечивают дополнительный уровень инкапсуляции. Интерфейс определяет набор методов, которые должны присутствовать в классе. В самом интерфейсе эти методы не реализуются, поэтому он представляет собой чисто логическую конструкцию. Пакеты и интерфейсы предоставляют дополнительную возможность для более рациональной организации программ и контроля их структуры.Пакеты

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

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