Текст книги "Java: руководство для начинающих (ЛП)"
Автор книги: Герберт Шилдт
Жанр:
Программирование
сообщить о нарушении
Текущая страница: 9 (всего у книги 36 страниц)
Выполнение этой программы дает следующий результат: 10 is even. 8 is even.
В данной программе метод isEven () вызывается трижды, и каждый раз ему передается новое значение. Рассмотрим подробнее ее исходный код. Обратите сначала внимание на то, каким образом вызывается метод isEven (). Его параметр указывается в круглых скобках. При первом вызове методу isEven () передается значение 10. Следовательно, когда метод isEven () начинает выполняться, параметр х получает значение 10. При втором вызове в качестве аргумента этому методу передается значение 9, которое и принимает параметр х. А при третьем вызове методу isEven () передается значение 8, которое опять же присваивается параметру х. Какое бы значение ни указать при вызове метода isEven (), его все равно получит параметр х.
В методе может быть определено несколько параметров, и в этом случае они разделяются запятыми. Допустим, в классе Factor имеется метод isFactor (), который определяет, является ли первый его параметр множителем второго, как показано ниже. class Factor { //В этом методе предусмотрены два параметра. boolean isFactor(int a, int b) { if( (b % a) == 0) return true; else return false; } } class IsFact { public static void main(String args[]) { Factor x = new Factor(); // При вызове методу isFactor() передаются два аргумента. if(х.isFactor(2, 20)) System.out.println("2 is factor"); if(x.isFactor(3, 20)) System.out.println("this won't be displayed"); } }
Обратите внимание на то, что при вызове метода isFactor () передаваемые ему значения также разделяются запятыми.
При использовании нескольких параметров для каждого из них определяется тип, причем типы параметров могут отличаться. Например, следующее объявление метода является корректным: int myMeth(int a, double b, float с) { // ... Добавление параметризированного метода в класс Vehicle
Параметризированный метод позволяет реализовать в классе Vehicle новую возможность: расчет объема топлива, необходимого для преодоления заданного расстояния. Назовем этот новый метод fuelneededO . Он получает в качестве параметра расстояние в милях, которое должно проехать транспортное средство, а возвращает необходимое для этого количество галлонов топлива. Метод f uelneeded () определяется следующим образом: double fuelneeded(int miles) { return (double) miles / mpg; }
Обратите внимание на то, что этот метод возвращает значение типа double. Это важно, поскольку объем потребляемого топлива не всегда можно выразить целым числом. Ниже приведен исходный код программы для расчета дальности действия транспортных средств с классом Vehicle, содержащим метод fuelneeded (). /* Добавление параметризированного метода, в котором производится расчет объема топлива, необходимого транспортному средству для преодоления заданного расстояния. */ class Vehicle { int passengers; // количество пассажиров int fuelcap; // емкость топливного бака int mpg; // потребление топлива в милях на галлон // возвратить дальность действия транспортного средства int range() { return mpg * fuelcap; } // рассчитать объем топлива, необходимого транспортному // средству для преодоления заданного расстояния double fuelneeded(int miles) { return (double) miles / mpg; } } class CompFuel { public static void main(String args[]) { Vehicle minivan = new Vehicle(); Vehicle sportscar = new Vehicle(); double gallons; int dist = 252; // присвоить значения полям в объекте minivan minivan.passengers = 7; minivan.fuelcap = 16; minivan.mpg = 21; // присвоить значения полям в объекте sportscar sportscar.passengers = 2; sportscar.fuelcap = 14; sportscar.mpg = 12; gallons = minivan.fuelneeded(dist) ; System.out.println("To go " + dist + " miles minivan needs " + gallons + " gallons of fuel."); gallons = sportscar.fuelneeded(dist); System.out.println("To go " + dist + " miles sportscar needs " + gallons + " gallons of fuel."); } }
Выполнение этой программы дает следующий результат: То до 252 miles minivan needs 12.0 gallons of fuel. To go 252 miles sportscar needs 21.0 gallons of fuel.
Пример для опробования 4.1. Создание справочного класса
Если попытаться кратко выразить сущ¬ ность классов, то следовало бы сказать, что класс инкапсулирует функциональные возможности. Иногда трудно определить, где оканчиваются одни функциональные возможности и начинаются другие. Класс должен быть стандартным блоком для компоновки приложения. Для этой цели класс необходимо спроектировать таким образом, чтобы он представлял собой одну функциональную единицу, выполняющую строго определенные действия. Следовательно, нужно стремиться к тому, чтобы классы были как можно более компактными, но в разумных пределах! Ведь классы, реализующие лишние функциональные возможности, делают код сложным для понимания и плохо структурированным, но классы со слишком ограниченными функциональными возможностями приводят к тому, что программа становится неоправданно фрагментированной. Как же найти золотую середину? В поисках ее наука программирования превращается в искусство программирования. Многие программисты считают, что такая способность приходит с опытом.
В качестве упражнения для приобретения нужных навыков работы с классами в этом проекте вам предстоит преобразовать в класс Help справочную систему, созданную в примере для опробования 3.3. Но прежде рассмотрим, какие для этого имеются основания. Во-первых, справочная система представляет собой один логический блок. Эта система лишь отображает синтаксис управляющих операторов Java. Ее функциональные возможности четко определены. Во-вторых, реализация справочной системы в виде класса представляет собой довольно изящное решение. Всякий раз, когда требуется отобразить подсказку для пользователя, достаточно создать экземпляр объекта справочной системы. И наконец, справочную информацию можно дополнить или изменить, не затрагивая остальные части программы, поскольку она инкапсулирована в классе.
Последовательность действий
Создайте новый файл HelpClassDemo. j ava. Ради экономии времени и труда на ввод исходного текста скопируйте файл Help3. j ava, созданный вами во время проработки примера для опробования 3.3, и сохраните его под именем HelpClassDemo.java.
Для того чтобы преобразовать справочную систему в класс, нужно сначала четко определить ее составные части. Так, в исходном файле Help3. j ava программы, реализующей справочную систему, имеется код, отвечающий за отображение меню, получение информации от пользователя, проверку достоверности ответа и отображение данных, соответствующих выбранному пункту меню. В этой программе имеется также цикл, который завершается при вводе символа q. По зрелом размышлении становится ясно, что средства организации меню, проверки достоверности ответа и отображения информации являются составными частями справочной системы. В то же время порядок получения данных от пользователя и обработки многократных запросов не имеет к системе непосредственного отношения. Таким образом, нужно создать класс, который отображает справочную информацию, меню для ее выбора и проверяет правильность сделанного выбора. Соответствующие методы класса можно назвать helpon (), showmenu () и isvalid ().
Создайте метод helpon (), исходный.код которого приведен ниже.void helpon(int what) { switch(what) { case '1': System.out.println("The if:n"); System.out.println("if(condition) statement;"); System.out.println("else statement;"); break; case '2': System.out.println("The switch:n"); System.out.println("switch(expression) {"); System.out.println(" case constant:"); System.out.println(" statement sequence"); System.out.println(" break;"); System.out.println(" // ..."); 140 Java 7: руководство для начинающих, 5-е издание System.out.println("}"); break; case '3': System.out.println("The for:n"); System.out.print("for(init; condition; iteration)"); System.out.println(" statement;"); break; case '4': System.out.println("The while:n"); System.out.println("while(condition) statement;"); break; case '5': System.out.println("The do-while:n"); System.out.println("do {"); System.out.println(" statement;"); System.out.println("} while (condition);"); break; case '6': System.out.println("The break:n"); System.out.println("break; or break label;"); break; case '7': System.out.println ("The continue': n") ; System.out.println("continue; or continue label;"); break; } System.out.println(); }
Далее создайте метод showmenu (), исходный код которого приведен ниже.void showmenu() { System.out.println("Help on:"); System.out.println(" 1. if"); System.out.println(" 2. switch"); System.out.println(" 3. for"); System.out.println (" 4. while"); System.out.println(" 5. do-while"); System.out.println(" 6. break"); System.out.println(" 7. continuen"); System.out.print("Choose one (q to quit): "); }
И наконец, создайте метод is valid (), исходный код которого приведен ниже.boolean isvalid(int ch) { if(ch < 'l1 | ch > *7' & ch != fq') return false; else return true; }
Добавьте созданные выше методы в класс Help, как показано ниже. class Help { void helpon(int what) { switch(what) { case '1' : System.out.println("The if:n"); Глава 4. Введение в классы, объекты и методы 141 System.out.println("if(condition) statement;"); System.out.println("else statement;"); break; case '2': System.out.println("The switch:n"); System.out.println("switch(expression) {"); System.out.println(" case constant:"); System.out.println(" statement sequence"); System, out .print'ln (" break;") ; System.out.println(" // ..."); System.out.println("}"); break; case '3': System.out.println("The for:n"); System.out.print("for(init; condition; iteration)"); System.out.println(" statement;"); break; case '4' : System.out.println("The while:n"); System.out.println("while(condition) statement;"); break; case '5': System.out.println("The do-while:n"); System.out.println("do {"); System.out.println(" statement;"); System.out.println("} while (condition);"); break; case '6': System.out.println("The break:n"); System.out.println("break; or break label;"); break; case '7': System.out.println("The continue:n"); System.out.println("continue; or continue label;"); break; } System.out.println(); } void showmenu() { System.out.println("Help on:"); System.out.println(" 1. if"); System.out.println(" 2. switch"); System.out.println(" 3. for"); System.out.println(" 4. while"); System.out.println(" 5. do-while"); System.out.println(" 6. break"); System.out.println(" 7. continuen"); System.out.print("Choose one (q to quit): "); } boolean isvalid(int ch) { if(ch < '1' | ch > '7' & ch != fq') return false; else return true; } }
Перепишите метод main () из примера для опробования 3.3 таким образом, чтобы использовать в нем новый класс Help. Сохраните новый исходный код в файле HelpClassDemo. j ava. Ниже приведен весь исходный код программы, реализующей справочную систему в файле HelpClassDemo. j ava. /* Пример для опробования 4.1. Преобразование в класс Help справочной системы из примера для опробования 3.3. */ class Help { void helpon(int what) { switch(what) { case '1': System.out.println("The if:n"); System.out.println("if(condition) statement;"); System.out.println("else statement;"); break; case '2': System.out.println("The switch:n"); System.out.println("switch(expression) {"); System.out.println(" case constant:"); System.out.println(" statement sequence"); System.out.println(" break;"); System, out .println (" // ...");, System.out.println("}"); break; case '3': System.out.println("The for:n"); System.out.print("for(init; condition; iteration)"); System.out.println(" statement;"); break; case '4': System.out.println("The while:n"); System.out.println("while(condition) statement;"); break; case '5': System.out.println("The do-while:n"); System.out.println("do {"); System.out.println(" statement;"); System.out.println("} while (condition);"); break; case '6': System.out.println("The break:n"); System.out.println("break; or break label;"); break; case '7': System.out.println("The continue:n"); System.out.println("continue; or continue label;"); break; } System.out.println(); } void showmenu() { System.out.println("Help on:"); System.out.println(" 1. if"); System.out.println(" 2. switch"); System.out.println(" 3. for"); System.out.println(" 4. while"); System.out.println(" 5. do-while"); System.out.println(" 6. break"); System.out.println(" 7. continuen"); System.out.print("Choose one (q to quit): "); boolean isvalid(int ch) { if(ch < 'l1 | ch > f 7' & ch != 'q') return false; else return true; } } class HelpClassDemo { public static void main(String args[]) throws java.io.IOException { char choice, ignore; Help hlpobj = new Help(); for (;;) { do { hlpobj.showmenu(); choice = (char) System.in.read(); do { ignore = (char) System.in.read(); } while(ignore != !n'); } while( !hlpobj.isvalid(choice) ); if(choice == 'q') break; System.out.println("n"); hlpobj.helpon(choice); } } }
Запустив эту программу на выполнение, вы увидите, что она ведет себя точно так же, как и предыдущая ее версия. Преимущество текущей ее версии заключается лишь в том, что теперь справочная система может быть использована повторно всякий раз, когда в этом возникнет потребность. Конструкторы
В предыдущем примере программы мы вынуждены были вручную устанавливать значения переменных экземпляра для каждого объекта типа Vehicle, как показано ниже. minivan.passengers = 7; minivan.fuelcap = 16; minivan.mpg =21;
Но такой подход вообще не применяется в программах, профессионально написанных на Java, по следующим причинам. Во-первых, существует большая вероятность допустить ошибку (можно, например, забыть установить значение одного из полей). И во-вторых, существует гораздо более простой и надежный способ решения подобной задачи: использовать конструктор.
Конструктор инициализирует объект при его создании. У конструктора такое же имя, как и у его класса, а с точки зрения синтаксиса он подобен методу. Но у конструкторов нет возвращаемого типа, указываемого явно. Как правило, конструкторы используются для задания первоначальных значений переменных экземпляра, определенных в классе, или же для выполнения любых других установочных процедур, которые требуются для создания полностью сформированного объекта.
У всех классов имеются конструкторы, независимо от того, определите вы их или нет, поскольку в Java автоматически предоставляется конструктор, используемый по умолчанию и инициализирующий все переменные экземпляра их значениями по умолчанию. Для большинства типов данных значением по умолчанию является нулевое, для типа bool – логическое значение false, а для ссылочных типов – пустое значение null. Но как только вы определите свой собственный конструктор, конструктор по умолчанию больше не используется.
Ниже приведен простой пример, демонстрирующий применение конструктора. // Простой конструктор. class MyClass { int х; // Конструктор класса MyClass. MyClass() { х = 10; } } class ConsDemo { public static void main(String args[]) { MyClass tl = new MyClass(); MyClass t2 = new MyClass(); System.out.println(tl.x + " " + t2.x); } }
В данном примере конструктор класса MyClass объявляется следующим образом: MyClass () { х = 10; }
В этом конструкторе переменной экземпляра х, определяемой в классе MyClass, присваивается значение 10. Этот конструктор вызывается оператором new при создании объекта данного класса. Ниже приведена строка кода, в которой используется оператор new. MyClass tl = new MyClass();
В этой строке кода для объекта tl вызывается конструктор MyClass (), в котором переменной экземпляра tl. х присваивается значение 10. То же самое происходит и для объекта t2. После вызова данного конструктора переменная экземпляра t2. х также получает значение 10. Таким образом, выполнение приведенного выше примера программы дает следующий результат: 10 10 Параметризированные конструкторы
В предыдущем примере использовался конструктор без параметров. В некоторых случаях этого оказывается достаточно, но зачастую конструктор должен принимать один или несколько параметров. В конструктор параметры вводятся таким же образом, как и в метод. Для этого достаточно объявить их в скобках после имени конструктора. Ниже приведен пример применения параметризированного конструктора класса MyClass. // Параметризированный конструктор. class MyClass { int х; //У этого конструктора имеется параметр. MyClass(int i) { х = i; } } class ParmConsDemo { public static void main(String args[]) { MyClass tl = new MyClass(10); MyClass t2 = new MyClass(88); System.out.println(tl.x + " " + t2.x); } }
Результат выполнения данной программы выглядит следующим образом: 10 88
В данной версии программы в конструкторе класса MyClass определяется единственный параметр i, который используется для инициализации переменной экземпляра х. При выполнении следующей строки кода значение 10 сначала передается параметру i данного конструктора, а затем присваивается переменной х: MyClass tl = new MyClass(10); Добавление конструктора в класс Vehicle
Теперь мы можем усовершенствовать класс Vehicle, добавив в него конструктор, в котором будут автоматически инициализироваться поля passengers, fuelcap и mpg при построении объекта. Обратите особое внимание на то, каким образом создаются объекты типа Vehicle. // Добавление конструктора. class Vehicle { int passengers; // количество пассажиров int fuelcap; // емкость топливного бака int mpg; // потребление топлива в милях на галлон // Это конструктор класса Vehicle. Vehicle(int р, int f, int m) { passengers = p; fuelcap = f; mpg = m; } // возвратить дальность действия транспортного средства int range() { return mpg * fuelcap; } // рассчитать объем топлива, необходимого транспортному // средству для преодоления заданного расстояния double fuelneeded(int miles) { return (double) miles / mpg; } } class VehConsDemo { public static void main(String args[]) { // сконструировать полностью объекты транспортных средств Vehicle minivan = new Vehicle(7, 16, 21); Vehicle sportscar = new Vehicle(2, 14, 12); double gallons; int dist = 252; gallons = minivan.fuelneeded(dist); System.out.println("To go " + dist + " miles minivan needs " + gallons + " gallons of fuel."); gallons = minivan.fuelneeded(dist); System.out.println("To go " + dist + " miles sportscar needs " + gallons + " gallons of fuel."); } }
При создании объекты minivan и sportscar инициализируются конструктором Vehicle (). Каждый такой объект инициализируется параметрами, указанными в конструкторе его класса. Например, в строке кода Vehicle minivan = new Vehicle(7, 16, 21);
значения 7, 16 и 21 передаются конструктору Vehicle () в качестве параметров при создании нового объекта minivan с помощью оператора new.
В итоге копии переменных passengers, fuelcap и mpg в объекте minivan будут содержать значения 7, 16 и 21 соответственно. Рассмотренная здесь версия программы дает такой же результат, как и ее предыдущая версия. Еще раз об операторе new
Теперь, когда вы ближе ознакомились с классами и их конструкторами, вернемся к оператору new, чтобы рассмотреть его более подробно. Ниже приведена общая форма этого оператора в контексте присваивания. переменная_класса = new имя_класса{список_аргументов)
где переменнаякласса обозначает тип переменной создаваемого класса, а имякласса – конкретное имя класса, реализуемого в виде экземпляра его объекта. Имя класса и списокаргументов в скобках, который может быть пустым, обозначают конструктор этого класса. Если в классе не определен его собственный конструктор, то в операторе new будет использован конструктор, предоставляемый в Java по умолчанию. Следовательно, оператор new может быть использован для создания объекта, относящегося к классу любого типа. Оператор new возвращает ссылку на вновь созданный объект, который получает переменнаякласса в результате присваивания в данной форме записи.
Оперативная память не бесконечна, и поэтому вполне возможно, что оператору new не удастся выделить память для объекта из-за нехватки доступной памяти. В этом случае возникает исключительная ситуация во время выполнения (подробнее об обработке исключительных ситуаций речь пойдет в главе 9). В примерах программ, представленных в этой книге, ситуация, связанная с исчерпанием оперативной памяти, не учитывается, но при написании реальных программ такую возможность, вероятно, придется принимать во внимание. «Сборка мусора» и методы завершения
Как было показано выше, при использовании оператора new свободная память для создаваемых объектов динамически выделяется из доступной буферной области оперативной памяти. Разумеется, оперативная память не бесконечна, и поэтому свободно доступная память рано или поздно исчерпывается. Это может привести к неудачному выполнению оператора new из-за нехватки свободной памяти для создания требуемого объекта. Именно по этой причине одной из главных функций любой схемы динамического распределения памяти является своевременное освобождение памяти от неиспользуемых объектов, чтобы сделать ее доступной для последующего перераспределения. Во многих языках программирования освобождение распределенной ранее памяти осуществляется вручную. Например, в C++ для этой цели служит оператор delete. Но в Java применяется другой, более надежный подход: “сборка мусора”.
Система “сборки мусора” в Java освобождает память от лишних объектов автоматически, действуя подспудно, незаметно и без всякого вмешательства со стороны программиста. “Сборка мусора” происходит следующим образом. Если ссылки на объект отсутствуют, то такой объект считается больше ненужным, и занимаемая им память в итоге освобождается. Эта утилизированная память может быть затем распределена для других объектов.
“Сборка мусора” происходит лишь время от времени по ходу выполнения программы. Она не состоится только потому, что существует один или несколько объектов, которые больше не используются. Следовательно, нельзя заранее знать или предположить, когда именно произойдет “сборка мусора”. Метод finalize ()
Существует возможность определить метод, который будет вызван непосредственно перед окончательным удалением объекта из памяти. Этот метод называется finalize(). Он позволяет убедиться, что объект больше не существует. Этот метод можно, например, использовать для закрытия файла, открытого проверяемым объектом.
Для того чтобы добавить в класс метод завершения, достаточно определить метод finalize (). Исполняющая система Java вызовет этот метод перед фактическим удалением объекта. В теле метода finalize () следует предусмотреть действия, которые должны быть выполнены непосредственно перед удалением объекта.
Ниже приведена общая форма метода finalize(). protected void finalize() { // здесь указывается код метода завершения }
Ключевое слово protected является здесь спецификатором, предотвращающим обращение к методу finalizeO за пределами класса. Этот и другие спецификаторы доступа подробнее рассматриваются в главе 6.
Следует, однако, иметь в виду, что метод finalize () вызывается непосредственно перед операцией “сборки мусора” по отношению к удаляемому объекту. Но он не вызывается в том случае, если объект оказывается за пределами области действия. Поэтому заранее невозможно предсказать, когда и при каких условиях метод finalize () будет выполнен. Так, если программа завершится до того, как будет запущена процедура “сборки мусора”, метод finalize () не будет выполнен. Таким образом, данный метод не пригоден для корректного освобождения занятых ресурсов или для других специальных целей, а тем более для нормального завершения работы программы. Короче говоря, метод finalize () имеет специальное назначение и поэтому редко требуется для завершения большинства программ.
Пример для опробования 4.2. Демонстрация «сборки мусора» и завершения ко^а
В связи с тем что “сборка мусора” начинается в произвольные моменты времени и выполняется в фоновом режиме, продемонстрировать ее действие не так-то просто, но это можно все же сделать с помощью метода finalize(). Напомним, этот метод вызывается в тот момент, когда объект должен быть удален. Но, как пояснялось ранее, объект не обязательно удаляется именно тогда, когда необходимость в нем отпадает. Вместо этого система “сборки мусора” дожидается того момента, когда освобождение памяти может быть произведено наиболее эффективно. Чаще всего для этого должно накопиться достаточно большое количество неиспользуемых объектов. Поэтому для демонстрации “сборки мусора” с помощью метода finalize () нужно создать и удалить как можно больше объектов, что и предстоит сделать в данном проекте.
Последовательность действий
Создайте новый файл Finalize.java.
Создайте класс FDemo, как показано ниже. class FDemo { int х;
FDemo(int i) { x = i;
}
// вызывается при утилизации объекта protected void finalize() { System.out.println("Finalizing " + x); }
// формирует объект, который тотчас уничтожается 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; }