前不久分享了一篇文章,将的是java动态绑定和向上转型,说实话还没仔细看这篇文章,自己很懒。不过对于给的第一个程序,作者的解释是参数在编译阶段被匹配,得出的总结是重载函数的实际调用版本由编译器绑定决定,而覆盖函数的实际调用版本由动态绑定决定。还是有点道理,不过对于程序,我觉得刚开始看的时候,未免把他想的太复杂了。先贴上程序,我修改了点。
class Base{
public void foo(Base x){
System.out.println("Base.Base");
}
public void foo(Derived x){
System.out.println("Base.Derived");
}
}
class Derived extends Base{
public void foo(Base x){
System.out.println("Derived.Base");
}
public void foo(Derived x){
System.out.println("Derived.Derived");
}
}
public class Main{
public static void whichFoo(Base arg1, Base arg2){
arg1.foo(arg2);
// System.out.println();
arg2.foo(arg1);
arg1.foo(arg1);
arg2.foo(arg2);
}
public static void main(String[] args){
Base b = new Base();
Derived d = new Derived();
whichFoo(b,b);
// b.foo(b);
System.out.println();
whichFoo(b,d);
// b.foo(d);
System.out.println();
whichFoo(d,b);
// d.foo(b);
System.out.println();
whichFoo(d,d);
// d.foo(d);
}
}
对于whichFoo中的参数,既然已经给定了是Base,那么在函数里调用xx.foo(argx)时,显然argx就是Base了,不会再动态改变了,不用想太复杂了!
如果将Base.foo(Base x)函数取消掉,那么编译时就给出错误:无法将foo(Derivide)应用于Base。
所以,对于调用重载的方法,编译器会根据参数决定调用哪个方法,所以作者总结的“重载函数的实际调用版本由编译器绑定决定,而覆盖函数的实际调用版本由动态绑定决定”还是比较容易理解的。但是也不应把参数传递想的太复杂了!