Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Программирование на Java.docx
Скачиваний:
2
Добавлен:
01.05.2025
Размер:
3.45 Mб
Скачать

Тема 2.14 Более пристальный взгляд на передачу аргументов

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

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

Листинг 2.15

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

public class Test {

public 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("а и b перед вызовом: " + a + " " + b);

ob.meth(a, b);

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

}

}

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

а и b перед вызовом: 15 20 а и b после вызова: 15 20

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

При передаче объекта методу ситуация изменяется коренным образом, поскольку по существу объекты передаются посредством вызова по ссылке. Следует помнить, что при создании переменной типа класса создается лишь ссылка на объект. Таким образом, при передаче этой ссылки методу, принимающий ее параметр будет ссылаться на тот же объект, на который ссылается аргумент. По сути это означает, что объекты передаются методам посредством вызова по ссылке. Изменения объекта внутри метода влияют на объект, использованный в качестве аргумента(листинг 2.16).

Листинг 2.16

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

public class Test {

public int a, b;

public Test(int i, int j) {

a = i;

b = j;

}

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

public void meth(Test o) {

o.a *= 2;

o.b /= 2;

}

}

public class CallByRef {

public static void main(String args[]) {

Test ob = new Test(15, 20);

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

ob.meth(ob);

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

}

}

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

ob.a и ob.b перед вызовом: 15 20 ob.a и ob.b после вызова: 30 10

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

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

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

 Тема 2.15 Возврат объектов

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

Листинг 2.17

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

public class Test {

public int а;

public Test(int i) {

а = i;

}

public Test incrByTen() {

Test temp = new Test(а + 10);

return temp;

}

}

public class RetOb {

public static void main(String args[]) {

Test ob1 = new Test(2);

Test ob2;

ob2 = ob1.incrByTen();

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

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

ob2 = ob2.incrByTen();

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

}

}

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

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

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

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