
- •Основы классов
- •Общая форма класса
- •Простой класс
- •Объявление объектов
- •Операция new
- •Представление методов
- •Добавление метода к классу Box
- •Возврат значений
- •Добавление метода с параметрами
- •Конструкторы
- •Параметризованные конструкторы
- •Ключевое слово this
- •Скрытие переменной экземпляра
- •Сборка "мусора"
- •Метод finalize()
- •Класс Stack
- •Перегрузка конструкторов
- •Использование объектов в качестве параметров
- •Передача аргументов
- •Возврат объектов
- •Рекурсия
- •Управление доступом
- •Статические элементы
- •Спецификатор final
- •Ревизия массивов
- •Вложенные и внутренние классы
- •Класс String
- •Использование аргументов командной строки
- •Наследование
- •Основы наследования
- •11 Тело класса }
- •Доступ к элементам и наследование
- •Практический пример
- •Переменная суперкласса может ссылаться на объект подкласса
- •Использование ключевого слова super
- •Вызов конструктора суперкласса с помощью первой формы super
- •Создание многоуровневой иерархии
- •II построить клон объекта
- •Когда вызываются конструкторы
- •Переопределение методов
- •Динамическая диспетчеризация методов
- •Зачем нужны переопределенные методы?
- •Применение переопределения методов
- •Использование абстрактных классов
- •Void meth() { // ошибка! Нельзя переопределять.
- •Класс Object
Объявление объектов
Объявление класса – это создание нового типа данных. Этот тип можно использовать для объявления соответствующих объектов. Однако получение объектов класса это двухшаговый процесс. Во-первых, нужно объявить переменную типа "класс". Она не определяет объект. Это просто переменная, которая может ссылаться на объект. Во-вторых, необходимо получить актуальную, физическую копию объекта и назначать ее этой переменной. Эти действия выполняются с помощью операции new. Операция new динамически (т. е. во время выполнения) распределяет память для объекта и возвращает ссылку на нее. Данная ссылка является адресом ячейки памяти, выделенной объекту вышеуказанной операцией, которая сохраняется в переменной. Таким образом, в Java все объекты класса должны быть распределены динамически. Рассмотрим подробности данной процедуры.
В предшествующих примерах программ для объявления объекта типа box использовалась строка вида:
Box mybox = new Box();
Этот оператор комбинирует два шага, как было только что описано. Чтобы продемонстрировать каждый шаг, его можно переписать так:
Box mybox; // объявить ссыпку на объект
mybox = new Вох(); // распределить память для Box-объекта
Первая строка объявляет mybox как ссылку на объект типа box. После того как эта строка выполняется, mybox содержит значение null, которое означает, что переменная еще не указывает на фактический объект. Любая попытка использовать mybox в этой точке приведет к ошибке во время компиляции. Следующая строка распределяет фактический объект и назначает ссылку на него переменной mybox. После того, как вторая строка выполняется, вы можете использовать mybox, как если бы это был объект box. Но в действительности mybox просто содержит адрес ячейки памяти фактического объекта box. Действие этих двух строк программы изображено на рис. 1.1.
3амечание Те, кто знаком с C/C++ вероятно заметили, что объектные ссылки кажутся похожими на указатели. Это подозрение, по существу, верно. Объектная ссылка подобна указателю. Главное различие (и ключ к безопасности Java) заключается в том, что манипулировать со ссылками как с указателями запрещено. Нельзя, например, заставить объектную ссылку указать на произвольное место в памяти или манипулировать ею как целым числом.
Операция new
Как только что было указано, операция new динамически распределяет память для объекта. Он имеет следующую общую форму:
class_var = new classnamе();
Здесь class_var – переменная типа "класс", которая создается; имя класса, экземпляр которого создается. За именем класса следуют круглые скобки, устанавливающие конструктор класса. Конструктор (constructor) определяет, что происходит, когда объект класса создается. Это важная часть всех классов. Конструкторы имеют много существенных атрибутов. Как будет показано ниже, большинство классов явно определяют свои собственные конструкторы (внутри своих определений). Однако если явный конструктор не определен, то Java автоматически обеспечит так называемый "конструктор по умолчанию" (default constructor) или умалчиваемый конструктор. Именно так выделяется память под класс box. При этом переменные экземпляра не инициализируются.
Здесь следует обратить внимание на то, что для простых (скалярных) типов операция new не используется. Простые типы Java реализованы не как экземпляры класса. Память для них распределяется статически при объявлении. Это сделано в интересах эффективности, т.е. Java может реализовывать простые типы более эффективно. Позже будут обсуждаться объектные версии простых типов, которые можно использовать в тех ситуациях, когда необходимы объекты этих типов.
Важно понять, что new распределяет память для объекта во время выполнения. Преимущество данного подхода состоит в том, что ваша программа может создавать столько объектов, сколько требуется в течение ее выполнения. Однако, возможно, что операция new не будет способна распределить память для объекта, потому что существует недостаток памяти, т. к. она конечна. Если это происходит, возникнет исключительная ситуация при работе программы. (Возможности обработки этих и других исключений также рассматриваются позднее). Для всех рассматриваемых примеров не стоит беспокоиться относительно нехватки памяти, но нужно помнить о такой ситуации при написании реальных программ.
Кроме того, следует обратить внимание на то, что во время выполнения операции присваивания ссылочные переменные объекта (object reference variables) не приводят к распределению памяти под новый объект. Так при выполнении фрагмента программы:
Box b1 = new Bоx() ; Box b2 = b1;
обе переменных (b1 и b2) будут ссылаться на один и тот же объект. Присваивание b1 = b2 не распределяет никакой памяти для b2 и не копирует какую-либо часть первоначального объекта. Эта операция просто помещает в b2 ссылку из b1 (создает только копию ссылки). Таким образом, любые изменения, сделанные в объекте через b2 затронут объект, на который ссылается b1, т. к. это один и тот же объект. Данная ситуация изображена на рис. 6-2.
Хотя b1 и b2 ссылаются на тот же самый объект, они не связаны каким-то другим способом. Например, присваивание b1= null просто «разорвет» ссылку b1 без воздействия на объект.
//...
Box bl = new Box();
Box b2 = bl;
//...
b1 = null;
//...
Здесь b1 была установлена в null, но Ь2 все еще указывает на первоначальный объект.