Вызов функции Java с перегрузкой - программирование

Вызов функции Java с перегрузкой

Я хочу знать, почему третий выход НЕ Б.

Вот мой код:

public class SimpleTests {
    public void func(A a) {
        System.out.println("Hi A");
    }
    public void func(B b) {
        System.out.println("Hi B");
    }
    public static void main(String[] args) {
        A a = new A();
        B b = new B();
        A c = new B();
        SimpleTests i = new SimpleTests();
        i.func(a);
        i.func(b);
        i.func(c);
    }
}
class A {}
class B extends A {}

И вот вывод:

Hi A
Hi B
Hi A

Может ли кто-нибудь сказать мне, почему 3-й выход - это Hi A, NOT Hi B поскольку реальный c является экземпляром B.

4b9b3361

Ответ 1

Вы запутываете перегрузку полиморфизмом.

При полиморфизме при создании экземпляра класса B, который является подклассом класса A, на который ссылается объект класса A, и перезаписывает метод класса A, вызов метода будет выполнять метод класса B.

При перегрузке вызываемый метод знает только тип объявления аргумента, а не инициализацию.

public class A {
    public void print() {
        System.out.println("A");
    }
}

public class B extends A {
    @Override
    public void print() {
        System.out.println("B");
    }
}    

public class Main {
    public static void main(String[] args) {
        A a = new A();
        B b = new B();
        A otherB = new B();
        a.print();
        b.print();
        otherB.print();
    }
}

Это приведет к выводу

A
B
B

Ответ 2

Вызовы перегруженных методов разрешаются на основе ссылочного типа (A) аргумента во время компиляции, а не типа объекта (B) во время выполнения. Вы указали, что переменная имеет тип A, поэтому она рассматривается как тип A

Ответ 3

JLS §8.4.9. Перегрузки:

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

В вашем примере используются типы компиляции:

A a = new A(); // A
^

B b = new B(); // B
^

A c = new B(); // A
^

Следовательно, выход:

Hi A
Hi B
Hi A