什么时候在Java中调用对象类型而不是对象的方法,特别是在静态绑定中?

时间:2013-08-21 23:15:11

标签: java oop inheritance casting static-binding

我的问题可能不太清楚。通过这个例子,我可以进一步解释。 当我阅读为此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

我的问题如下: 为什么在第一个版本中调用来自A类的p(int),而在第二个版本中调用来自B类的p(double)

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 = new A();

将c分配给新对象

因此,这个声明B c = new A();创建了一个A类实例并分配给B类变量。现在每当在c上执行方法调用时,编译器首先检查B中是否存在方法(因为它是B类型),但实际调用的方法是对象(它是一个A实例)。 为什么在上面的例子中没有看到这种行为?或者如果我的推理是错误的,请善意地纠正我。

谢谢

1 个答案:

答案 0 :(得分:1)

在第一个版本中,覆盖一个方法,在第二个方法中重载

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

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

您可以在“Effective Java”一书中找到相关内容 - 第41项,第191页:

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