一个多态问题
class Father {
public void say() {
System.out.println("I am father!");
}
}
class Son extends Father {
@Override
public void say() {
System.out.println("I am son");
}
}
public class Test {
public void say(Father father) {
System.out.println("say1");
father.say();
}
public void say(Son son) {
System.out.println("say2");
son.say();
}
public static void main(String[] args) {
Father father = new Son();
new Test().say(father);
}
}
J2SE基础忘光了,为什么结果是
say1
I am son
而不是
say2
I am son
------解决方案--------------------
java在运行时才检测实际类型,编译器只看引用类型
------解决方案--------------------要调用哪个重载方法是在编译时作出决定的,而选择被覆盖方法是在运行时进行的。
请楼主参考《Effective Java》一书第165页第41条:慎用重载,可以很好地解答楼主的问题。
本人菜鸟,只是刚好在看这本书,所以不能很好地用自己的语言进行回答。
------解决方案--------------------这个问题说清楚,lz需要明白两个概念:静态编译和运行期的动态绑定。就是说因为你在程序中 Father father = new Son(); 将father声明成了Father类,这样在编译器就仅仅会将其当成Father,而不会关注其实际的子类是啥,所以编译器就绑到了第一个say()方法,就像有有LS说的,如果程序中没有
public void say(Father father) {
System.out.println("say1");
father.say();
} 方法,程序会直接编译都通不过的;
而调用具体对象上的某一个方法,这就是运行期的动态绑定在起作用,就是说运行时,系统会得到对象的实际类(Son),然后调用实际类的方法。
------解决方案--------------------如你定义一个Object,并且有它的子类,在编译时编译器不能确定你传入的实际对象是什么,但是它肯定是Object的子类的一个对象。所以编译时指定为Object才允许编译通过。
本例中,编译的时候只管Father father。编译器认为它就是个father,那就只能调用带有Father参数的方法,你调用带有Son的方法,你自己是知道的,但编译时编译器还不知道。。多态运用的是动态绑定机制,动起来才知道。。
实际在调用中发现你传入的Father对象可以转型为son,于是调用的是son里面的方法。
我是这么理解的。