Когда метод типа объекта вместо объекта вызывается в 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

Другие вопросы по тегам