16

16


53

Учтите, что следующая конструкция не разрешена, хотя в С и С++ она воз¬можна:

{

int х = 12, {

int х = 96. // неверно

}

}

Компилятор объявит, что переменная х уже была определена. Таким обра¬зом, возможность языков С и С++ «прятать» переменные во внешней области действия не поддерживается. Создатели Java посчитали, что она приводит к из¬лишнему усложнению программ.

Область действия объектов

Объекты Java имеют другое время жизни в сравнении с примитивами. Объект, созданный оператором Java new, будет доступен вплоть до конца области дейст¬вия. Если вы напишете:

{

String s = new Stnng("строка"); } // конец области действия

то ссылка s исчезнет в конце области действия. Однако объект String, на кото¬рый указывала s, все еще будет занимать память. В показанном фрагменте кода невозможно получить доступ к объекту, потому что единственная ссылка вы¬шла за пределы видимости. В следующих главах вы узнаете, как передаются ссылки на объекты и как их можно копировать во время работы программы.

Благодаря тому, что объекты, созданные new, существуют ровно столько, сколько вам нужно, в Java исчезает целый пласт проблем, присущих С++. В С++ приходится не только следить за тем, чтобы объекты продолжали суще¬ствовать на протяжении своего жизненного цикла, но и удалять объекты после завершения работы с ними.

Возникает интересный вопрос. Если в Java объекты остаются в памяти, что же мешает им постепенно занять всю память и остановить выполнение про¬граммы? Именно это произошло бы в данном случае в С++. Однако в Java су¬ществует сборщик мусора (garbage collector), который наблюдает за объектами, созданными оператором new, и определяет, на какие из них больше нет ссылок. Тогда он освобождает память от этих объектов, которая становится доступной для дальнейшего использования. Таким образом, вам никогда не придется «очи¬щать» память вручную. Вы просто создаете объекты, и как только надобность в них отпадет, эти объекты исчезают сами по себе. При таком подходе исчезает целый класс проблем программирования: так называемые «утечки памяти», когда программист забывает освобождать занятую память.

Создание новых типов данных

Если все является объектом, что определяет строение и поведение класса объ¬ектов? Другими словами, как устанавливается тип объекта? Наверное, для этой цели можно было бы использовать ключевое слово type («тип»); это было бы

Создание новых типов данных

вполне разумно. Впрочем, с давних времен повелось, что большинство объект¬но-ориентированных языков использовали ключевое слово class в смысле «Я собираюсь описать новый тип объектов». За ключевым словом class следует имя нового типа. Например:

class ATypeName { /* Тело класса */ }

Эта конструкция вводит новый тип, и поэтому вы можете теперь создавать объект этого типа ключевым словом new:

ATypeName а = new ATypeNameO;

Впрочем, объекту нельзя «приказать» что-то сделать (то есть послать ему не¬обходимые сообщения) до тех пор, пока для него не будут определены методы.

Поля и методы

При определении класса (строго говоря, вся ваша работа на Java сводится к оп¬ределению классов, созданию объектов этих классов и посылке сообщений этим объектам) в него можно включить две разновидности элементов: поля (fields) (иногда называемые переменными класса) и методы (methods) (еще на¬зываемые функциями класса). Поле представляет собой объект любого типа, с которым можно работать по ссылке, или объект примитивного типа. Если ис¬пользуется ссылка, ее необходимо инициализировать, чтобы связать с реаль¬ным объектом (ключевым словом new, как было показано ранее).

Каждый объект использует собственный блок памяти для своих полей дан¬ных; совместное использование обычных полей разными объектами класса не¬возможно. Пример класса с полями:

class DataOnly { int i, double d; boolean b;

}

Такой класс ничего не делает, кроме хранения данных, но вы можете соз¬дать объект этого класса:

DataOnly data = new DataOnlyO;

Полям класса можно присваивать значения, но для начала необходимо уз¬нать, как обращаться к членам объекта. Для этого сначала указывается имя ссыл¬ки на объект, затем следует точка, а далее — имя члена, принадлежащего объекту:

ссылка.член Например:

data i = 47;

data.d =1.1,

data.b = false;

Также ваш объект может содержать другие объекты, данные которых вы хоте¬ли бы изменить. Для этого просто продолжите «цепочку из точек». Например:

55

myPlane.leftTank.capacity = 100;

Класс DataOnly не способен ни на что, кроме хранения данных, так как в нем отсутствуют методы. Чтобы понять, как они работают, необходимо разобраться, что такое аргументы и возвращаемые значения. Вскоре мы вернемся к этой теме.

Значения по умолчанию для полей примитивных типов

Если поле данных относится к примитивному типу, ему гарантированно при¬сваивается значение по умолчанию, даже если оно не было инициализировано явно (табл. 2.2).

Таблица 2.2. Значения по умолчанию для полей примитивных типов

Примитивный тип Значение по умолчанию

boolean false

char ЛиОООО' (null)

byte (byte)O

short (short)O

int 0

long OL

float O.Of

double O.Od

Значения по умолчанию гарантируются Java только в том случае, если пере¬менная используется как член класса. Тем самым обеспечивается обязательная инициализация элементарных типов (что не делается в С++), которая умень¬шает вероятность ошибок. Однако значение по умолчанию может быть невер¬ным или даже недопустимым для вашей программы. Переменные всегда лучше инициализировать явно.

Такая гарантия не относится к локальным переменным, которые не являются полями класса. Допустим, в определении метода встречается объявление пере¬менной

int х;

Переменной х будет присвоено случайное значение (как в С и С++); она не будет автоматически инициализирована нулем. Вы отвечаете за присвоение правильного значения перед использованием х. Если же вы забудете это сде¬лать, в Java существует очевидное преимущество в сравнении с С++: компиля¬тор выдает ошибку, в которой указано, что переменная не была инициализиро¬вана. (Многие компиляторы С++ предупреждают о таких переменных, но в Java это считается ошибкой.)

Report Page