Выбрать главу

// формирует объект, который тотчас уничтожается void generator(int i) { FDemo о = new FDemo(i).;

} }

В конструкторе данного класса устанавливается значение переменной экземпляра х, определяемое передаваемым параметром. В данном примере переменная экземпляра х служит в качестве идентификатора объекта. При утилизации объекта метод finalize () отображает значение переменной х. Обратите особое внимание на метод generator (). В нем создается объект типа FDemo, который сразу же уничтожается. Этот метод будет использован в дальнейшем.

Создайте класс Finalize, как показано ниже.class Finalize { public static void main(String args[]) { int count; FDemo ob = new FDemo(0); /* А теперь сформировать большое количество объектов. В какой-то момент должна начаться "сборка мусора". Примечание: количество формируемых объектов, возможно, придется увеличить, чтобы принудить "сборку мусора". */ for(count=l; count < 100000; count++) ob.generator(count); } }

В классе Finalize сначала создается исходный объект ob типа FDemo. Затем из этого объекта формируется 100000 других аналогичных объектов. С этой целью вызывается метод generator () для объекта ob. На различных этапах данного процесса вступает в действие процедура “сборки мусора”. Частота активизации данной процедуры зависит от целого ряда факторов, в том числе от объема свободной памяти и типа операционной системы. Но в любом случае в какой-то момент вы увидите сообщения, выводимые на экран в процессе выполнения метода finalize (). Если ни одного сообщения не появится, попробуйте увеличить число создаваемых объектов, изменив условие завершения цикла for.

Ниже приведен весь исходный код программы из файла Finalize.java. /* Пример для опробования 4.2. Демонстрация "сборки мусора" и метода finalize(). */ class FDemo { int x; FDemo(int i) { x = i; } // вызывается при утилизации объекта protected void finalize () { System.out.println("Finalizing " + x) ; } // формирует объект, который тотчас уничтожается void generator(int i) { FDemo о = new FDemo(i); } } class Finalize { public static void main(String args[]) { int count; FDemo ob = new FDemo(0); /* А теперь сформировать большое количество объектов. В какой-то момент должна начаться "сборка мусора". Примечание: количество формируемых объектов, возможно, придется увеличить, чтобы принудить "сборку мусора". */ for(count=l; count < 100000; count++) ob.generator(count); } } Ключевое слово this

И в завершение этой главы рассмотрим ключевое слово this. Когда метод вызывается, ему автоматически передается ссылка на вызывающий объект, т.е. тот объект, для которого вызывается данный метод. Эта ссылка обозначается ключевым словом this. Следовательно, ключевое слово this обозначает именно тот объект, по ссылке на который действует вызываемый метод. Для того чтобы стало яснее назначение ключевого слова this, рассмотрим сначала пример программы, в которой создается класс Pwr, в котором вычисляется результат возведения числа в некоторую целочисленную степень. class Pwr { double b; int e; double val; Pwr(double base, int exp) { b = base; e = exp; val = 1; if(exp==0) return; for( ; exp>0; exp—) val = val * base; } double get_pwr() { return val; } } class DemoPwr { public static void main(String args[]) { Pwr x = new Pwr(4.0, 2); Pwr у = new Pwr(2.5, 1); Pwr z = new Pwr (5.7, 0); System.out.println(x.b + "raised to the 11 + x.e + " poweris " + x.get_pwr()); System.out.println(y.b + "raised to the " + y.e + " power is 11 + y.get_pwr()j; System.out.println(z .b + 11 raised to the " + z.e + " power is " + z.get pwr()); } }

Как вам должно быть уже известно, в теле метода можно непосредственно обращаться к другим членам класса, не указывая имя объекта или класса. Так, в методе get_pwr () имеется следующий оператор: return val;

Он означает, что из данного метода должна быть возвращена копия значения переменной val, связанной с вызывающим объектом. Этот оператор можно переписать следующим образом: return this.val;

где ключевое слово this ссылается на объект, для которого был вызван метод get_pwr (). Следовательно, this.val — это ссылка на копию переменной val в данном объекте. Так, если бы метод get pwr () был вызван для объекта х, ключевое слово this в приведенном выше операторе ссылалось бы на объект х. Оператор, в котором отсутствует ключевое слово this, на самом деле является не более чем сокращенной записью.

Ниже приведен исходный код класса Pwr, написанный с использованием ключевого слова this. class Pwr { double b; int e; double val; Pwr(double base, int exp) { this.b = base; this.e = exp; this.val = 1; if(exp==0) return; for( ; exp>0; exp—) this.val = this.val * base; } double get_pwr() { return this.val; } }

На самом деле ни один программирующий на Java не напишет класс Pwr подобным образом, поскольку, добавляя ключевое слово this, он не получит никаких преимуществ. В то же время стандартная форма записи тех же самых операторов выглядит намного проще. Но в ряде случаев ключевое слово this может оказаться очень полезным. Например, синтаксис языка Java не запрещает использовать имена параметров или локальных переменных, совпадающие с именами глобальных переменных. В этом случае локальная переменная или параметр скрывает переменную экземпляра. А доступ к скрытой переменной экземпляра позволяет получить ключевое слово this. Так, приведенный ниже пример конструктора класса Pwr () синтаксически правилен, но подобного стиля программирования рекомендуется все же избегать. Pwr(double b, int e) { // Здесь ключевое слово this обозначает ссылку // на переменные b и е, а не на параметры, this.b = b; this.e = е; val = 1; if(е==0) return; for( ; е>0; е—) val = val * b; }

В данной версии конструктора класса Pwr имена параметров совпадают с именами переменных экземпляра, скрывая их. А ключевое слово this используется здесь для того, чтобы “раскрыть” переменные экземпляра.

Упражнение для самопроверки по материалу главы 4

В чем отличие класса от объекта?

Как определяется класс?

Чью собственную копию содержит каждый объект?

Покажите, как объявить объект counter класса MyCounter, используя два отдельных оператора.

Как должен быть объявлен метод myMeth, принимающий два параметра, а и b, типа int и возвращающий значение типа double?

Как должно завершаться выполнение метода, возвращающего некоторое значение?

Каким должно быть имя конструктора?

Какие действия выполняет оператор new?

Что такое “сборка мусора” и какие действия она выполняет? Зачем нужен метод finalize()?

Что означает ключевое слово this?

Может ли конструктор иметь один или несколько параметров?

Если метод не возвращает значения, то как следует объявить тип этого метода?

Глава 5 Дополнительные сведения о типах данных и операторах

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

Представление о массивах

Создание многомерных массивов

Создание нерегулярных массивов

Представление об альтернативном синтаксисе объявления массивов

Присваивание ссылок на массивы

Применение переменной экземпляра length

Использование разновидности for-each цикла for

Манипулирование символьными строками

Употребление аргументов командной строки

Использование поразрядных операторов

Применение оператора ?

В этой главе мы возвращаемся к обсуждению типов данных и операторов Java. В ней речь пойдет, в частности, о массивах, классе String, поразрядных операторах и тернарном операторе ?. Кроме того, мы рассмотрим разновидность цикла for, реализованную лишь в самых последних версиях языка. Внимание также будет уделено аргументам командной строки. Массивы

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