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
和运行时类型B
的aObj
变量。
在决定允许和不允许的内容时,编译器只会考虑静态类型 。
对你的问题:
1.为什么我不能通过aObj获取该变量,尽管它是指B类?
因为(通常)编译器无法知道 aObj
在运行时将引用B
对象,所以它只会引用某种forms的A
对象。 由于.b
在所有A
对象上都不可用,因此编译器会认为“比抱歉更安全”并且禁止它。
2.为什么我能够接受方法show()?
因为此方法在所有A
对象中都可用(如果它未在子类中声明,则它仍然从A
inheritance)。
aObj
是A
类型的局部变量。 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); } }
-
因为A里面没有变量b,即使你将B传递给A,你仍然有一个A对象,里面没有变量b。 因此,尝试访问b将给出编译时错误。
-
在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()