1

我的问题可能不是很清楚。通过这个例子,我可以进一步解释。当我阅读为此Static vs Dynamic Binding Logic发布的答案时,我得到了这个问题。

有两个版本的代码,两者完全一样,除了参数类型的变化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)在第一个版本中调用 A 类,而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 实例)。为什么在上面的例子中没有看到这种行为?或者如果我的推理是错误的,请纠正我。

谢谢

4

1 回答 1

1

在第一个版本中,您覆盖了一个方法,而在第二个方法中,您重载了它。

在第一个版本p中,您同时拥有class Aclass B。当您调用时c.p(...),编译器使用静态类型c创建调用。在运行时,代码使用类的虚拟表(如果您不熟悉,请阅读它)来找到正确的多态方法。

在第二个版本中,编译器在编译时为您执行从 int 到 double 的强制转换,然后在运行时再次使用虚拟表A来查找带有签名的方法p(double)(因为它在编译时将 int 强制转换为静态 -类型合规性)。虚拟表指向方法 inB因为A不覆盖它。

您可以在“Effective Java”一书中进一步阅读它 - 第 41 条,第 191 页:

selection among overloaded methods is static, while selection among overridden methods is dynamic

于 2013-08-21T23:37:01.760 回答