Помощничек
Главная | Обратная связь


Археология
Архитектура
Астрономия
Аудит
Биология
Ботаника
Бухгалтерский учёт
Войное дело
Генетика
География
Геология
Дизайн
Искусство
История
Кино
Кулинария
Культура
Литература
Математика
Медицина
Металлургия
Мифология
Музыка
Психология
Религия
Спорт
Строительство
Техника
Транспорт
Туризм
Усадьба
Физика
Фотография
Химия
Экология
Электричество
Электроника
Энергетика

Использование объектов в качестве параметров



До сих пор мы использовали в качестве параметров методов только простые типы. Однако существует практика передачи методам объектов. Например, рассмотрим следующую простую программу:

 

// Объекты можно передавать методам в качестве параметров.

class Test {

int a, b;

Test(int i, int j) {

a = i;

b = j;

}

// возвратить true, если о равно вызывающему объекту

boolean equals(Test o) {

if(o.a == a && o.b == b) return true;

else return false;

}

}

 

class Passob {

public static void main(String args[]) {

Test ob1 = new Test(100, 22);

Test ob2 = new Test(100, 22);

Test ob3 = new Test(-1, -1);

 

System.out.println("ob1 == ob2: " + ob1.equals(ob2));

System.out.println("ob1 == ob3: " + ob1.equals(ob3));

}

}

 

Эта программа генерирует следующий вывод:

 

ob1 == ob2: true

ob1 == ob3: false

 

Не трудно видеть, что метод equals() внутри класса Test сравнивает два объекта на равенство и возвращает результат. То есть, он сравнивает вызывающий объект с тем, который передан методу. Если они содержат те же значения, то метод возвращает true. Иначе, он возвращает false. Обратите внимание, что параметр o в методе equals() указывает Test в качестве своего типа. Хотя Test – это тип класса, созданный программой, он используется точно таким же способом, как и встроенные типы Java.

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

 

// Здесь Box позволяет одному объекту инициализировать другой.

class Box {

double width;

double height;

double depth;

// построить клон объекта

Box(Box ob) { // переслать объект конструктору

width = ob.width;

height = ob.height;

depth = ob. depth;

}

// конструктор для всех размеров блока

Box(double w, double h, double d) {

width = w;

height = h;

depth = d;

}

// конструктор блока без размеров

Box() {

width = -1; // использовать -1 для указания

height = -1; // неинициализированного

depth = -1; // блока

}

// конструктор для куба

Box(double len) {

width = height = depth = len;

}

// создать и возвратить объем

double volume() {

return width * height * depth;

}

}

class OverloadCons2 {

public static void main(String args[]) {

// создать блоки с использованием различных конструкторов

Box myboxl = new Box(10, 20, 15);

Box mybox2 = new Box ();

Box mycube = new Box(7);

Box myclone = new Box(myboxl);

double vol;

 

// получить объем первого блока

vol = myboxl.volume ();

System.out.println("Объем myboxl равен " + vol);

 

// получить объем второго блока

vol = mybox2.volume();

System.out.println("Объем mybox2 равен " + vol);

 

// получить объем куба

vol = mycube.volume ();

System.out.println("Объем cube равен " + vol);

 

// получить объем клона

vol = myclone.volume();

System.out.println("Объем clone равен " + vol);

}

}

 

Когда вы начинаете создавать собственные классы, обычно нужно организовывать много форм конструкторов, что позволит образовывать объекты удобным и эффективным способом.

Передача аргументов

Вообще, существуют два способа, с помощью которых машинный язык может передавать аргумент подпрограмме. Первый способ – передача аргумента по значению. Этот метод копирует значение аргумента в формальный параметр подпрограммы. Поэтому любые изменения этого параметра подпрограммой не имеют никакого влияния на соответствующий аргумент вызова. Второй способ – передача аргумента по ссылке. В этом методе ссылка на параметр (а не его значение) передается параметру. Внутри подпрограммы она используется, чтобы обратиться к фактическому параметру, указанному в вызове. Это означает, что изменения параметра будут влиять на аргумент, использованный для вызова подпрограммы. Java использует оба метода, в зависимости от того, что передается во время вызова подпрограмме.

Когда методу передается простой тип, он передается по значению. Таким образом, то, что происходит с параметром, который принимает аргумент, никак не влияет на сам аргумент (т.е. аргумент при этом не изменяется). Например, рассмотрим следующую программу:

 

// Простые типы передаются по значению.

class Test {

void meth(int i, int j) {

i *= 2;

j /= 2;

}

}

 

class CallByValue {

public static void main(String args[]) {

Test ob = new Test();

int a = 15, b = 20;

 

System.out.println("a и b перед вызовом: " + a + " " + b); ob.meth(a, b);

System.out.println("a и b после вызова: " + a + " " + b) ;

}

}

 

Вывод этой программы:

 

a и b перед вызовом: 15 20

a и b после вызова: 15 20

 

Как видите, операции, которые происходят внутри meth(), никак не влияют на значения a и b, используемые в вызове (их значения здесь не изменялись до 30 и 10, хотя метод meth() и выполнил соответствующие вычисления над своими параметрами).

Когда вы передаете методу объект, ситуация драматически изменяется, потому что объекты передаются по ссылке. Имейте в виду, что при создании переменной типа «класс», вы создаете только ссылку на объект. Таким образом, когда вы передаете эту ссылку методу, принимающий ее параметр будет ссылаться на тот же самый объект, что и аргумент. Это и означает, что объекты передаются методам по ссылке. Все изменения объекта внутри метода затрагивают объект, используемый как аргумент. Например, рассмотрим следующую программу:

 

// Объекты передаются по ссыпке.

class Test {

int a, b;

Test(int i, int j) {

a = i;

b = j;

}

// передать объект

void meth(Test o) {

o.a *= 2;

o.b /= 2;

}

}

 

class CallByRef {

public static void main(String args[]) {

Test ob = new Test(15, 20);

 

System.out.println("ob.a и ob.b перед вызовом: " + ob.a + " " + ob.b);

ob.meth(ob);

System.out.println("ob.a и ob.b после вызова: " + ob.a + " " + ob.b);

}

}

 

Эта программа генерирует следующий вывод:

 

ob.a и ob.b перед вызовом: 15 20

ob.a и ob.b после вызова: 30 10

 

В этом случае действия внутри meth() воздействовали на объект, используемый как аргумент. При передаче объектной ссылки методу сама ссылка передается по значению. Однако, т.к. передаваемое значение ссылается на объект, копия этого значения будет ссылаться на тот же объект, что и соответствующий аргумент.

Замечание. Простые типы передаются методу по значению, а объекты – по ссылке.

Возврат объектов

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

 

// Возврат объекта.

class Test {

int a;

Test(int i) {

a = i;

}

 

Test incrByTen() {

Test temp = new Test(a+10);

return temp;

}

}

 

class RetOb {

public static void main(String args[]) {

Test ob1 = new Test(2);

Test ob2;

 

ob2 = ob1.incrByTen() ;

System.out.println("ob1.a: " + ob1.a);

System.out.println("ob2.a: " + ob2.a);

 

ob2 = ob2.incrByTen();

System.out.println("ob2.a после повторного увеличения: " + ob2.a);

}

}

 

Вывод, сгенерированный этой программой:

 

ob1.a: 2

ob2.a: 12

ob2.a после повторного увеличения: 22

 

Каждый раз, когда incrByTen() вызывается, создается новый объект, и ссылка на него возвращается вызывающей подпрограмме.

Из предыдущей программы можно сделать следующий важный вывод: т.к. все объекты распределяются динамически с помощью операции new, вас не должен беспокоить выход объекта из области его видимости, потому что метод, в котором он был создан, завершается. Объект продолжает существовать, пока где-то в вашей программе присутствует ссылка на него. Когда же ссылок нет, то в следующем сеансе сборки «мусора» объект будет утилизирован.

Ревизия массивов

Массивы были представлены в этой книге раньше, чем были рассмотрены классы. Теперь, когда известны классы, для массивов можно сделать одно важное обобщение: их можно реализовать в форме объектов. В связи с этим имеется специальный атрибут массива, преимуществом которого вы, вероятно, захотите воспользоваться. Речь идет об экземплярной переменной length, которая определяет размер (длину) массива, т.е. число элементов, содержащихся в нем. Все массивы-объекты имеют эту переменную, и она всегда содержит размер массива. Следующая программа демонстрирует указанное свойство:

 

// Эта программа демонстрирует элемент длины массива.

class Length {

public static void main(String args[]) {

int a1[] = new int[10];

int a2[] = {3, 5, 7, 1, 8, 99, 44, -10};

int a3[] = {4, 3, 2, 1};

System.out.println("Размер a1 равен " + a1.length);

System.out.println("Размер a2 равен " + a2.length);

System.out.println("Размер a3 равен " + a3.length);

}

}

 

Эта программа отображает (на экран) следующий вывод:

 

Размер a1 равен 10

Размер a2 равен 8

Размер a3 равен 4

 

Здесь видно, что отображается размер каждого массива. Имейте в виду, что значение length не имеет никакого отношения к числу элементов, которые фактически используются. Она отражает только число элементов, на которое массив рассчитан.

 




Поиск по сайту:

©2015-2020 studopedya.ru Все права принадлежат авторам размещенных материалов.