Вызов функции 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.
Ответы
Ответ 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