A ab = new B();
这里ab的引用类型是A,但是它指向的内存是类型为B的一个实例
想对ab进行方法调用,你调用的方法都必须在 class A里面有的才行(因为你的引用类型为A)
这里 class A有show(A obj) show(D obj)着两个方法
ab.show(b) 在class A中没有找到类型匹配的方法,但是对b进行类型提升后,可以找到 show(A obj)方法,同理 ab.show(c)也是show(A obj)方法;但是ab内存地址指向一个类型为B内存空间,如果class B Override 了 class A的show(A obj)方法,则调用B的方法,反之,则调用A自己的方法
可以猜测 D d = new D(); ab.show(d)的结果是 A and D
如果注释掉 class A的 show(A obj)方法, ab.show(b) ab.show(c)都会出错。
这里你只要记住,能调用那些方法,由引用类型决定,具体执行情况,由实际内存对象类型决定
以下是我的见解,接触java不久,也不知道具体对不对,但是这是我认为合理的解释:
java有编译期和运行期,当代码编译时候(这个时候还没有内存对象创建),ab编译成的字节码中描述的是A,对你写的第一个ab.show()方法标记的是A中的方法,此时A中没有show(B),所以这个时候b就向上造型为A,show方法标记就为A中的show(A),然后运行期执行的时候,就是调用的内存对象,这个时候show方法要调用的时候就找的是具体对象,即ab调用B中的show,这个时候show()方法调用时,JVM发现在具体对象ab中有重写的show(A)方法,于是就输出的是B and A。
得出这样的结论是因为刚我在我的机器上跑程序的时候,发现,删掉B中的show(A)方法,控制台打印的是A and A;而且将代码A ab = new B()改成B ab = new B()结果就是B and B。
另外那些不仔细看代码就瞎说的人真是不负责任!还有个JAVA专家呢,不知所云!
前面是b楼主应该没有疑问啊,这里是ab的真实对象就是B
为什么后面是a,因为子类的方法对父类来说是不可见的,你写ab.show(b),他认为你掉的是A的show(A obj)。你如果用的是eclipse的话就很方便,按住ctrl,点击ab.show(b),你看他肯定会帮你追踪到A的show(A)方法那里去。好,既然掉的是show(A)方法,在运行时他发现ab其实是B类型,他就会找到B重载了父类A的方法,也就是B的show(A)方法。
这里说到底为什么不是B and B,就是B里面的show(B)完全是一个新的方法,并不是继承的父类的,你如果在A的里面再写一个show(B),就会出现你要的结果了
如果你想再了解清楚一点的话,你可以再上面的基础上再这样改,结果更好玩
A ab = new B();
A b = new B();
A c = new C();
System.out.println(ab.show(b));
System.out.println(ab.show(c));
It suprise me as well. I am digging deeper.
Note: Overloaded methods should be used sparingly, as they can make code much less readable.
如果 修改成
B ab = new B();
就能得到想要的结果
在 A ab = new B(); 的情况下,
ab 被当成了 A 类对象,所以ab.show(b),对于 A 类只能调用A#show(A obj),但是A#show(A) 已经被B#show(A)覆盖,所以输出 B and A
ab.show(c) 同理
ab.show(new D()) 就会输出 A and D,所以ab已经被多态了,B#show(B)没法被调用到了
JAVA软件工程师孙成 | 合作机构: 知道网友专家 最快回答
他回答的就是标准答案,我的回答比他详细点
您好,提问者:
A ab = new B(); 这句话,呵呵
你在B中写一个A中没有的方法,然后你ab调用不到的。
也就是说编译是B,运行是A类。