为什么java ref vars基于实际对象调用方法,因为变量基于ref变量类型?

时间:2011-07-29 12:58:14

标签: java inheritance

在超类A和子类B中,我将变量abc分别设为10和20,并将方法callme()覆盖在子类中。

如果我这样做

A a = new B(); 
B b = B(new A());

然后如果我写

a.callme() -> calls B's method
b.callme() -> calls A's method. 

这是因为基于实际对象调用方法。

如果我这样做

str = a.abc; // will print 10 , based upon ref var type A

str = b.abc; // will print 20 , based upon ref var type B

为什么会有这种差异?为什么两个方法和变量都不能根据实际对象进行访问?

由于

2 个答案:

答案 0 :(得分:2)

请记住,实例变量永远不会被覆盖,它们隐藏。它是决定将访问其实例变量的引用类型。

在子类中,方法callme()被覆盖。因此,根据动态方法调度机制,它是决定在运行时调用哪个方法的对象类型。这是因为,对象是在运行时创建的。

E.g

class A {
       int abc = 10;

       public void callme() { 
           System.out.println("In class A");
        }
   }

class B extends A {   
       int abc = 20;  // hidden, not overidden

        public void callme() { 
           System.out.println("In class B");
        }

        public static void main(String [] args) {
        A a = new A();
        a.callme(); // calls A's callme() method. 

        B b = new B();
        b.callme(); // calls B's callme() method.
       }
 }

答案 1 :(得分:0)

方法有一个实现,而字段只存储值/对象。能够覆盖方法的实现是有意义的。但我认为不需要“覆盖”一个领域。为什么不直接从子类中删除声明并使用超类的字段?

另一方面,也可以隐藏方法。但你必须把它们变成私人的。

class OuterClass {
    void test() {
        InnerSubClass isc = new InnerSubClass();
        isc.m(); // prints "In subclass"
        ((InnerSuperClass) isc).m(); // prints "In superclass"
    }
    class InnerSuperClass {
        private void m() {
            System.out.println("In superclass");
        }
    }
    class InnerSubClass extends InnerSuperClass {
        private void m() {
            System.out.println("In subclass");
        }
    }
}