Ниже приведен результат выполнения данной программы.Minivan can carry 7 with a range of 336Sportscar can carry 2 with a range of 168
Как видите, данные из объекта minivan отличаются от соответствующих данных из объекта sportscar. Это обстоятельство иллюстрирует приведенный ниже рисунок.
Порядок создания объектовВ рассмотренных ранее примерах программ для объявления объекта типа Vehicle использовалась следующая строка кода:Vehicle minivan = new Vehicle();
Эта строка кода выполняет две функции. Во-первых, в ней объявляется переменная класса Vehicle под именем minivan. Эта переменная еще не определяет объект, она лишь имеет возможность ссылаться на объект. И во-вторых, в этой строке кода создается физическая копия объекта, а ссылка на него присваивается переменной minivan. И делается это с помощью оператора new.
Оператор new динамически (т.е. в процессе выполнения программы) выделяет память для объекта и возвращает ссылку на него. Эта ссылка, по существу, представляет собой адрес области памяти, выделяемой для объекта оператором new. Ссылка на объект сохраняется в переменной. Таким образом, память для объектов всех классов в Java выделяется динамически.
Обе упомянутые функции приведенной выше строки кода можно записать следующим образом, чтобы разделить их и показать по отдельности:Vehicle minivan; // объявить ссылку на объектminivan = new Vehicle(); // выделить память для объекта типа Vehicle
В первой строке кода minivan объявляется как ссылка на объект типа Vehicle. Следует иметь в виду, что minivan — это переменная, которая может ссылаться на объект, а не сам объект. В данный момент переменная minivan пока еще не ссылается на объект. Во второй строке кода создается новый объект типа Vehicle, а ссылка на него присваивается переменной minivan. С этого момента переменная minivan оказывается связанной с объектом.Переменные ссылочного типа и присваивание
В операции присваивания переменные ссылочного типа действуют иначе, чем переменные такого простого типа, как, например, int. Когда одна переменная простого типа присваивается другой, ситуация оказывается довольно простой. Переменная, находящаяся в левой части оператора присваивания, получает копию значения переменной, находящейся в правой части этого оператора. Когда же одна переменная ссылки на объект присваивается другой, ситуация несколько усложняется, поскольку такое присваивание приводит к тому, что переменная, находящаяся в левой части оператора присваивания, ссылается на тот же самый объект, на который ссылается переменная, находящаяся в правой части этого оператора. Сам же объект не копируется. В силу этого отличия присваивание переменных ссылочного типа может привести к несколько неожиданным результатам. В качестве примера рассмотрим следующий фрагмент кода:Vehicle carl = new Vehicle();Vehicle car2 = carl;
На первый взгляд, переменные carl и car2 ссылаются на совершенно разные объекты, но на самом деле это не так. Переменные carl и саг2, напротив, ссылаются на один и тот же объект. Когда переменная carl присваивается переменой саг2, в конечном итоге переменная саг 2 просто ссылается на тот же самый объект, что и переменная carl. Следовательно, этим объектом можно оперировать с помощью переменной carl или саг2. Например, после очередного присваиванияcarl.mpg = 26;
оба метода println() в операторах их вызоваSystem.out.println(carl.mpg);System.out.println(car2.mpg);
выводят одно и то же значение: 26.Несмотря на то что обе переменные, carl и саг2, ссылаются на один и тот же объект, они никак иначе не связаны друг с другом. Например, в результате следующей последовательности операций присваивания просто изменяется объект, на который ссылается переменная саг2:Vehicle carl = new Vehicle();Vehicle car2 = carl;Vehicle carS = new Vehicle();car2 = сагЗ; // Теперь переменные car2 и сагЗ// ссылаются на один и тот же объект.
После выполнения этой последовательности операций присваивания переменная саг2 ссылается на тот же самый объект, что и переменная сагЗ. А ссылка на объект в переменной carl не меняется.Методы
Как пояснялось выше, переменные экземпляра и методы являются двумя основными составляющими классов. До сих пор класс Vehicle, рассматриваемый здесь в качестве примера, содержал только данные, но не методы. Хотя классы, содержащие толькоданные, вполне допустимы, у большинства классов должны быть также методы. Методы представляют собой подпрограммы, которые манипулируют данными, определенными в классе, а во многих случаях они предоставляют доступ к этим данным. Как правило, другие части программы взаимодействуют с классом посредством его методов.
Метод состоит из одного или нескольких операторов. В грамотно написанной программе на Java каждый метод выполняет только одну функцию. У каждого метода имеется свое имя, по которому он вызывается. В общем, методу в качестве имени можно присвоить любой действительный идентификатор. Следует, однако, иметь в виду, что идентификатор main () зарезервирован для метода, с которого начинается выполнение программы. Кроме того, в качестве имен методов нельзя использовать ключевые слова Java.
В этой книге методы именуются в соответствии с условными обозначениями, принятыми в литературе по Java. В частности, после имени метода следуют круглые скобки. Так, если методу присвоено имя getval, то в тексте книги он упоминается в следующем виде: getval (). Такая форма записи помогает отличать имена методов от имен переменных при чтении книги.
Ниже приведена общая форма объявления метода.возращаемый_тип имя (список_параметров) {// тело метода}
где возращаемыйтип обозначает тип данных, возвращаемых методом. Этот тип должен быть действительным, в том числе и типом создаваемого класса. Если метод не возвращает значение, то в качестве возвращаемого для него следует указать тип void. Далее, имя обозначает конкретное имя, присваиваемое методу. В качестве имени метода может служить любой допустимый идентификатор, не приводящий к конфликтам в текущей области объявлений. И наконец, списокпараметров — это последовательность пар, состоящих из типа и идентификатора и разделенных запятыми. Параметры представляют собой переменные, получающие значение аргументов, передаваемых методу при его вызове. Если у метода отсутствуют параметры, то список параметров оказывается пустым.Добавление метода в класс Vehicle
Как пояснялось ранее, методы класса обычно выполняют действия над данными в составе класса и предоставляют доступ к этим данным. Напомним, что метод main () в предыдущих примерах вычислял дальность действия транспортного средства, умножая емкость топливного бака на число миль, которые оно может проехать, потребив единичный объем топлива (в данном случае — галлон). И хотя такой расчет формально считается правильным, его лучше всего производить в пределах самого класса Vehicle. Аргументы в пользу такого решения очевидны: дальность действия транспортного средства зависит от потребления топлива в милях на галлон и емкости топливного бака, а обе эти величины инкапсулированы в классе Vehicle. Благодаря добавлению в класс Vehicle метода, предназначенного для расчета дальности, улучшается объектно-ориентированная структура кода.
Для того чтобы добавить метод в класс Vehicle, его следует объявить в пределах этого класса. Например, приведенный ниже вариант класса Vehicle содержит метод range (), определяющий и отображающий дальность действия транспортного средства.
// Добавление метода range в класс Vehicle,class Vehicle { int passengers; // количество пассажиров int fuelcap; // емкость топливного бака int mpg; // потребление топлива в милях на галлон // отобразить дальность действия транспортного средства // Метод range() относится к классу Vehicle. // Обратите внимание на то, что переменные fuelcap и трд // указываются напрямую без имени объекта и оператора-точки. void range() { System.out.println("Range is " + fuelcap * mpg); }}class AddMeth { public static void main(String args[]) { Vehicle minivan = new Vehicle(); Vehicle sportscar = new Vehicle(); int rangel, range2; // присвоить значения полям в объекте minivan minivan.passengers = 7; minivan.fuelcap = 16; minivan.mpg = 21; // присвоить значения полям в объекте sportscar sportscar.passengers = 2; sportscar.fuelcap = 14; sportscar.mpg = 12; System.out.print("Minivan can carry " + minivan.passengers + ". "); minivan.range(); // отобразить дальность действия мини-фургона System.out.print("Sportscar can carry " + sportscar.passengers + ". "); sportscar.range(); // отобразить дальность действия спортивной машины }}