java中的动态方法调度

class A{ int a=10; public void show(){ System.out.println("Show A: "+a); } } class B extends A{ public int b=20; public void show(){ System.out.println("Show B: "+b); } } public class DynamicMethodDispatch { public static void main(String[] args) { A aObj = new A(); aObj.show(); //output - 10 B bObj = new B(); bObj.show(); //output - 20 aObj = bObj; //assigning the B obj to A.. aObj.show(); //output - 20 aObj = new B(); aObj.show(); //output - 20 System.out.println(bObj.b); //output - 20 //System.out.println(aObj.b); //It is giving error } } 

在上面的程序中,我正在尝试调用aObj.b时遇到错误。
1.为什么我不能通过aObj获取该变量,尽管它是指B类?
2.为什么我能够访问方法show()?

您必须区分aObj静态类型aObj运行时类型

代码如

 A aObj = new B(); 

导致具有静态类型A和运行时类型BaObj变量。

在决定允许和不允许的内容时,编译器只会考虑静态类型

对你的问题:

1.为什么我不能通过aObj获取该变量,尽管它是指B类?

因为(通常)编译器无法知道 aObj在运行时将引用B对象,所以它只会引用某种forms的A对象。 由于.b在所有A对象上都不可用,因此编译器会认为“比抱歉更安全”并且禁止它。

2.为什么我能够接受方法show()?

因为此方法在所有A对象中都可用(如果它未在子类中声明,则它仍然从Ainheritance)。

aObjA类型的局部变量。 A没有名为b成员,只在您的子类B 。 如果你想使用b ,你需要声明一个B类型的变量,当然你只能为它分配B (或子类,如果有的话)的实例。

A声明方法show() ,但是重写子类B的实现。

这种行为称为virtual method invocation ,它是Java中polymorphism一个重要方面。 你应该看看这个教程 。

 class A{ // class A has variable a and method show(); int a=10; public void show(){ System.out.println("Show A: "+a); } } class B extends A{ //class B inherits variables and methods of A. // so class B has variable a, b and show(). Also, show is overridden by class B. public int b=20; public void show(){ System.out.println("Show B: "+b); } } 
  1. 因为A里面没有变量b,即使你将B传递给A,你仍然有一个A对象,里面没有变量b。 因此,尝试访问b将给出编译时错误。

  2. 在show()的情况下,A和B都有这个方法,所以你在这里做的实际上是在运行时覆盖它。 这只不过是多态性 。 因为A已经有方法show(),后来被B覆盖,

A =新B(); 一场表演();

这将在运行时运行B的show()方法。

方法和字段具有不同的多态行为。

将被调用的方法是实例的运行时类型的方法

 aObj=new B(); //new B() 

将被调用的字段是您声明的引用类型的字段

 A aObj = new A(); // A aObj 

即使在A中没有show()方法,以下工作也会起作用。

 aObj = new B(); aObj.show(); //calls B's show()