Правила перегрузки Java и наследования
Я учился, потому что у меня есть экзамен, и у меня не так много проблем с большинством Java, но я наткнулся на правило, которое я не могу объяснить. Здесь фрагмент кода:
public class A {
public int method(Object o) {
return 1;
}
public int method(A a) {
return 2;
}
}
public class AX extends A {
public int method(A a) {
return 3;
}
public int method(AX ax) {
return 4;
}
}
public static void main(String[] args) {
Object o = new A();
A a1 = new A();
A a2 = new AX();
AX ax = new AX();
System.out.println(a1.method(o));
System.out.println(a2.method(a1));
System.out.println(a2.method(o));
System.out.println(a2.method(ax));
}
Это возвращает:
1
3
1
3
Пока я ожидаю, что он вернется:
1
3
1
4
Почему это так, что тип a2 определяет, какой метод вызывается в AX?
Я читал о перегрузке правил и наследования, но это кажется не совсем понятным, что я не смог найти точное правило. Любая помощь будет принята с благодарностью.
Ответы
Ответ 1
Поведение этих вызовов метода продиктовано и описывается Спецификацией языка Java (ссылка в разделе 8.4.9).
При вызове метода (§15.12) количество фактических аргументов (и любые явные аргументы типа) и типы времени компиляции аргументы используются во время компиляции для определения подписи метод, который будет вызываться (§15.12.2). Если метод, который должен быть invoked - это метод экземпляра, фактический метод для вызова будет определяется во время выполнения, используя динамический поиск метода (§15.12.4).
В вашем примере компилятор Java определяет самое близкое совпадение типа компиляции экземпляра, к которому вы вызываете свой метод. В этом случае:
A.method(AX)
Ближайший метод относится к типу A с сигнатурой A.method(A)
. Во время выполнения динамическая отправка выполняется по фактическому типу A (который является экземпляром AX), и, следовательно, это метод, который фактически называется:
AX.method(A)
Ответ 2
Я разъясню это более простым способом. См., Когда вы делаете объект sub class с суперклассической ссылкой, как вы это делали.
Всегда помните, что когда вы вызываете ссылку на суперклассу, не имеет значения, что объект относится к подклассу, он перейдет к суперклассу, метод проверки с этим именем вместе с собственно сигнатурой есть или нет.
теперь, если он найдет его, чем он проверит, переопределен ли он? если да, то это будет идти к методу подкласса, как здесь. другой мудрый он выполнит тот же метод суперкласса.
Я могу привести вам пример этого... просто скрыть
public int method(A a) {
return 3;
}
и проверьте свой ответ, вы получите 1 2 1 2, почему, потому что он дает первостепенное значение для ссылки. потому что вы его переопределили, а не назвали его, поэтому он дал 3...!! надеюсь, что это будет большой, но понятной. Счастливое обучение
Ответ 3
a2, на который ссылаются как A и JVM, используя ссылку сначала (а не acutal объект, как вы ожидали).