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()?
答案 0 :(得分:5)
您必须区分aObj
的静态类型和aObj
的运行时类型。
代码如
A aObj = new B();
会生成aObj
变量,其中包含静态类型A
和运行时类型B
。
在决定允许和不允许的内容时,编译器只会费心查看静态类型。
问题:
1.为什么我不能通过aObj访问该变量,虽然它是指B类?
因为(通常)编译器无法知道 aObj
在运行时将引用B
对象,所以只会引用某些对象A
对象的形式。由于.b
并非在所有A
个对象上都可用,因此编译器会认为“比对不起更安全”并禁止它。
2.为什么我能够访问方法show()?
因为此方法 在所有A
个对象中都可用(如果它未在子类中声明,它仍然继承自A
)。
答案 1 :(得分:2)
aObj
是A
类型的局部变量。 A
没有名为b
的成员,仅在您的子类B
中。如果要使用b
,则需要声明类型为B
的变量,但当然只能为B
(或子类,如果有的话)分配实例。< / p>
A
声明了方法show()
,但您覆盖了子类B
中的实现。
答案 2 :(得分:1)
此行为称为virtual method invocation
,它是Java中polymorphism
的一个重要方面。你应该看看这个tutorial。
答案 3 :(得分:0)
方法和字段具有不同的多态行为。
将被调用的方法是实例的运行时类型的方法
aObj=new B(); //new B()
将被调用的字段是您声明的引用类型的字段
A aObj = new A(); // A aObj
即使A中没有show()方法,以下内容仍然有效。
aObj = new B();
aObj.show(); //calls B's show()
答案 4 :(得分:0)
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都有这个方法,所以你在这里做的实际上是在运行时覆盖它。这只不过是Polymorphism。因为A已经有方法show(),后来被B覆盖,
a a = new B(); a.show();
这将在运行时运行B的show()方法。