Скрытие переменной экземпляра
Как известно, в Java недопустимо объявление двух локальных переменных с одним и тем же именем внутри той же самой, или включающей области действия идентификаторов. Заметим, что вы можете иметь локальные переменные, включая формальные параметры для методов, которые перекрываются с именами экземплярных переменных класса. Однако, когда локальная переменная имеет такое же имя, как переменная экземпляра, локальная переменная скрывает переменную экземпляра. Вот почему width, height и depth не использовались как имена параметров конструктора Box() внутри класса Box. Если бы они были использованы для именования этих параметров, то, скажем width, как формальный параметр, скрыл бы переменную экземпляра width. Хотя обычно проще указывать различные имена, существует другой способ обойти эту ситуацию. Поскольку this позволяет обращаться прямо к объекту, это можно применять для разрешения любых конфликтов пространства имен, которые могли бы происходить между экземплярными и локальными переменными. Ниже представлена другая версия Box(), которая использует width, height и depth для имен параметров и затем применяет this, чтобы получить доступ к переменным экземпляра с теми же самыми именами:
// Используйте этот вариант конструктора
// для разрешения конфликтов пространства имен.
Box(double width, double height, double depth) {
this.width = width;
this.height = height;
this.depth = depth;
}
Использование this в указанном контексте иногда может привести к путанице, так что некоторые программисты предпочитают не применять имена локальных переменных и формальных параметров, которые совпадают с переменными экземпляра. Конечно, другие программисты, наоборот, верят, что это хорошее соглашение — использовать одинаковые имена — для ясности, и this — чтобы преодолеть скрытие переменной экземпляра. Какой подход принимаете вы — это вопрос вкуса.
Передача аргументов
Существуют два способа, с помощью которых машинный язык может передавать аргумент подпрограмме. Первый способ — передача аргумента по значению. Этот метод копирует значение аргумента в формальный параметр подпрограммы. Поэтому любые изменения этого параметра подпрограммой не имеют никакого влияния на соответствующий аргумент вызова. Второй способ — передача аргумента по ссылке. В этом методе ссылка на параметр (а не его значение) передается параметру. Внутри подпрограммы она используется, чтобы обратиться к фактическому параметру, указанному в вызове. Это означает, что изменения параметра будут влиять на аргумент, использованный для вызова подпрограммы. 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("а и b перед вызовом: "+a+" "+b);
ob.meth(a, b);
System.out.println("а и b после вызова: "+a+" "+b);
}
}
Когда вы передаете методу объект, ситуация изменяется, потому что объекты передаются по ссылке. При создании переменной типа "класс", создается только ссылка на объект. Таким образом, когда вы передаете эту ссылку методу, принимающий ее параметр будет ссылаться на тот же самый объект, что и аргумент. Это и означает, что объекты передаются методам по ссылке. Все изменения объекта внутри метода затрагивают объект, используемый как аргумент. Например, рассмотрим следующую программу:
// Объекты передаются по ссылке.
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.а и ob.b перед вызовом: " + ob.a + " " + ob.b);
ob.meth(ob);
System.out.println("ob.a и ob.b после вызова: " + ob.a + " " + ob.b);
}
}
Интересно отметить, что при передаче объектной ссылки методу сама ссылка передается по значению. Однако, т. к. передаваемое значение ссылается на объект, копия этого значения будет ссылаться на тот же объект, что и соответствующий аргумент.
