Правила перегрузки 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 объект, как вы ожидали).