вы увидите значение 7 и до и после выполнения метода f(), потому что он менял локальную переменную a, а не переменную-аргумент x.
Очень часто у метода встречаются параметры ссылочного типа. В этом случае в локальную переменную-параметр копируется значение аргумента-ссылки, которое, среди прочего, содержит адрес, по которому хранится значение переменной. После этого метод будет работать непосредственно с объектом, на который ссылается аргумент, при помощи локальной копии аргумента-ссылки. Следующий пример поясняет это.
class Dummy2{
private static void f(int[] a){ a[0] = 5;
}
public static void main(String[] args){ int[] x = {7};
System.out.println("До: " + x[0]); f (x);
System.out.println("После: " + x[0]);
}
}
Теперь переменная x — это ссылка на массив, которая копируется в локальную переменную, созданную для параметра a. Ссылка a направляется на тот же массив, что и ссылка x. Она меняет нулевой элемент массива, и мы получаем "До: 7", "После: 5". По-прежнему сделана передача аргумента по значению, но теперь аргумент — это ссылка, и в метод f () передается ссылка, а не объект, на который она направлена.
Передача ссылок по значению приводит иногда к неожиданным результатам. В следующем примере:
class Dummy3{
private static void f(int[] a){ a = new int[]{5};
}
public static void main(String[] args){ int[] x = {7};
System.out.println("До: " + x[0]); f (x);
System.out.println("После: " + x[0]);
}
}
мы опять оба раза увидим на экране число 7. Хотя теперь в методе f() изменилась ссылка на массив — параметр этого метода, а не сам массив, но изменилась копия a ссылки x, а не она сама. Копия a получила новое значение, она направлена на новый массив {5}, но сама ссылка x осталась прежней, она по-прежнему направлена на массив {7}.
В языке Java применяется только передача аргументов по значению.
Имя метода, число и типы параметров образуют
Тип возвращаемого значения не входит в сигнатуру метода, значит, методы не могут различаться только типом результата их работы.
Например, в классе Automobile мы записали метод moveTo (int x, int y), обозначив пункт назначения его географическими координатами. Можно определить еще метод moveTo(String destination) для указания географического названия пункта назначения и обращаться к нему так:
oka.moveTo("Москва");
Такое дублирование методов называется их
Если же записать метод в подклассе с тем же именем, параметрами и типом возвращаемого значения, что и в суперклассе, например:
class Truck extends Automobile{ void moveTo(int x, int y){
// Какие-то действия...
}
// Что-то еще, содержащееся в классе Truck...
}
то он перекроет метод суперкласса.
Определив экземпляр класса Truck, например:
Truck gazel = new Truck();
и записав gazel.moveTo(25, 150), мы обратимся к методу класса Truck. Произойдет
При переопределении метода его сигнатура и тип возвращаемого значения должны полностью сохраняться. Если в подклассе мы изменим тип, количество или порядок следования параметров, то получим новый метод, не переопределяющий метод суперкласса. Если изменим только тип возвращаемого значения, то получим ошибку, которую "заметит" компилятор.
Проверку соответствия сигнатуры переопределяемого метода можно возложить на компилятор, записав перед методом подкласса аннотацию ©Override, как это сделано в листинге 2.2. В этом случае компилятор пошлет на консоль сообщение об ошибке, если сигнатура помеченного метода не будет соответствовать сигнатуре ни одного метода суперкласса с тем же именем.
При переопределении метода права доступа к нему можно только расширить, но не сузить. Открытый метод public должен остаться открытым, защищенный protected может стать открытым, но не может стать закрытым.
Можно ли внутри подкласса обратиться к методу суперкласса? Да, можно, если уточнить имя метода словом super, например super.moveTo(30, 40). Можно уточнить и имя метода, записанного в этом же классе, словом this, например this.moveTo(50, 70), но в данном случае это уже излишне. Таким же образом можно уточнять и совпадающие имена полей, а не только методов.