Когда метод типа объекта вместо объекта вызывается в Java, особенно в статической привязке?
Мой вопрос может быть не очень ясным просматривая этот пример, я могу объяснить дальше. Когда я читал ответы, опубликованные для этой логики Static vs Dynamic Binding, я получил этот вопрос.
Существует две версии кода, которые абсолютно одинаковы, за исключением изменения типа параметра для Class B p (double i)
version 1:
import java.lang.*;
public class X
{
public static void main(String [] args)
{
B c = new A();
c.p(10);
c.p("AAA");
((A)c).p(10);
}
}
class B {
public void p(String s)
{
System.out.println("B: my string is " + s);
}
public void p(int i)
{
System.out.println("B: twice my double is: " + i*2);
}
}
class A extends B{
public void p(int i)
{
System.out.println("A: my number is " + i);
}
}
Here the output is :
A:my number is 10
B: my string is AAA
A: my number is 10
version 2:
import java.lang.*;
public class X
{
public static void main(String [] args)
{
B c = new A();
c.p(10);
c.p("AAA");
((A)c).p(10);
}
}
class B {
public void p(String s)
{
System.out.println("B: my string is " + s);
}
public void p(double i)
{
System.out.println("B: twice my double is: " + i*2);
}
}
class A extends B{
public void p(int i)
{
System.out.println("A: my number is " + i);
}
}
Here the output is :
B:twice my double is 20.0
B: my string is AAA
A: my number is 10
мой вопрос заключается в следующем: почему p(int)
из класса А называется в первой версии, а p(double)
из класса B называется во втором варианте.
version 1:
methods of A
A -----> p(string), p(int)- this is overridden from Class B
method of B
B ------> p(string), p(int)
version 2:
methods of A
A -----> p(string), p(double), p(int) No more overriding
method of B
B ------> p(string), p(double)
когда я заявляю B c;
Я инициализирую ссылочную переменную, которая имеет тип B
затем я назначаю c новому объекту, c = new A();
отсюда и эта декларация B c = new A();
создает экземпляр класса A и назначает переменную типа B. Теперь, когда вызовы методов выполняются на c, компилятор сначала проверяет, существуют ли методы в B (так как это тип B), но фактический метод, который является Вызванный объект (который является экземпляром A). почему это поведение не видно в приведенном выше примере? или если мои рассуждения неверны, пожалуйста, поправьте меня.
Спасибо
1 ответ
В первой версии вы переопределяете метод, а во втором методе вы перегружаете его.
В первой версии у вас есть p
в обоих class A
а также class B
, Когда вы звоните c.p(...)
компилятор использует статический тип c
создать вызов. Во время выполнения код использует виртуальную таблицу класса (читайте об этом, если вы не знакомы), чтобы найти правильный полиморфный метод.
Во второй версии компилятор выполняет приведение от int к удвоению для вас во время компиляции, а затем во время выполнения он снова использует виртуальную таблицу A
найти метод с подписью p(double)
(потому что он бросил int во время компиляции для соответствия статическому типу). Виртуальная таблица указывает на метод в B
так как A
не отменяет это.
Подробнее об этом вы можете прочитать в книге "Эффективная Java" - ст. 41, стр. 191:
selection among overloaded methods is static, while selection among overridden methods is dynamic