所以,我有这个:
public class A {
public int a = 0;
public void m(){
System.out.println("A"+a);
}
}
而且:
public class B extends A {
public int a = 5 ;
public void m (){
System.out.println("B"+a);
}
public static void main(String[] args) {
A oa = new A();
B ob = new B();
A oab = ob;
oa.m();
ob.m();
oab.m();
System.out.println("AA"+oa.a);
System.out.println("BB"+ob.a);
System.out.println("AB"+oab.a);
}
}
输出:
A0
B5
B5
AA0
BB5
AB0
我不明白为什么 oab.m(); 输出 B5 而不是 A0 。谁可以给我解释一下这个?
答案 0 :(得分:9)
这就是多态性的全部意义。 oab
的具体类型为B
(因为对象是使用new B()
创建的)。所以调用方法B.m()
。
查看http://en.wikipedia.org/wiki/Polymorphism_%28computer_science%29中的Animal示例,了解它为什么有用。当你有一只动物,而这只动物是一只猫时,你会期待它说“喵!”当你说话时。
答案 1 :(得分:1)
B ob = new B();
A oab = ob;
类似于
A oab=new B();
I don't understand why oab.m(); output is B5 instead of A0
因为你创建B
的对象并将其引用到A所以m()
被继承,这就是为什么B's version
被m()
调用的原因。
答案 2 :(得分:0)
A oa = new A();
B ob = new B();
A oab = ob;
从上面的代码中,ob是B类的一个实例。它可以存储在A类的变量中,因为A扩展为B.但是由于存储的Object实例是B,因此它不知道A的m()功能。
因此,输出为B5
答案 3 :(得分:0)
在继承中,实际的方法调用取决于实际对象的类型,而不取决于引用的类型。
B ob = new B();
A oab = ob;
此处oab
是A
类型的引用变量,但它指向B
类型的对象,即ob
,因此在运行时oab.m()
将调用覆盖类m()
B
方法
答案 4 :(得分:0)
在Java中有类似后期绑定(polymorphism)的东西。这意味着方法代码在编译时(早期绑定)时没有链接,而是在运行时。在调用oab.m();
时,JVM正在检查aob
引用(在您的情况下为B
)中的对象的实际类型(类),并基于该信息调用该类中的方法代码。这就是oab.m();
返回B5
的原因。
您还需要知道后期绑定仅适用于方法,而不适用于字段。对于字段,值将由引用类型确定,因此oab.a
将返回0
而不是5
。
答案 5 :(得分:0)
想象一下,你有以下几点:
public class C extends A {
public int a = 7 ;
public void m (){
System.out.println("C"+a);
}
现在,如果你在Main方法中有这个...
C oc = new C();
A oac = oc;
oac.m();
...你希望最后一次调用输出特定于C类的东西。
关键是 B是A , C是A ,但每个都有A包含的更多特定版本的值,以及何时你要求提供这些数据,应该返回它们的具体版本。
现在你可以这样做:
// Get an instance of B or C, but you don't
// care which - could be either:
A someVersionOfA = getAnInstanceOfA();
// This works no matter if you've got an instance
// of B or C, but the result should vary accordingly:
someVersionOfA.m();
正如其他人提到的那样,将 A 视为“动物”,将 B 视为“cat”,将 C 视为“狗”。如果 m()表示“发出一些噪音”,那么调用m()会导致“Meow”或“Woof!”取决于实例 getAnInstanceOfA()返回。
答案 6 :(得分:0)
您刚刚将B的内部地址复制为A,然后将其替换。
B继承自A,所以没有编译问题。
最后,对A的引用被破坏,现在它是对B
的引用的副本