首先需要了解方法的调用过程:
1.编译器查看对象声明类型与方法。假设调用x.f(param),且隐式参数类型X声明为C类型的对象。
需要注意的是:可能存在多个名称为f的方法,但是参数类型不一样,例如f(String),f(int),这时编译器会列举
出C类中方法名为f和C类的父类中修饰符为public的f方法,到此为止,编译器已经找到所有可能被调用的方法。
2.查看方法调用时提供的参数类型。如果所有名为f的方法中存在一个与提供参数相匹配的的方法,例如x.f(“hello”)
那么编译器就会查找f(String),而不是f(int).此过程如果找到多个此方法或者没有找到,就会报错。
静态绑定:
在编译期就准确知道调用的是哪一个方法。如果是private方法,static方法,final方法或者是构造器,那么就可以直接确定是调用那个方法。
private方法:只能是本类中的方法,因为private方法对子类不可见
static方法:是类方法,可以被继承,但是不能被重写
final方法:不能被继承,因此会直接确定
动态绑定:
调用的方法依赖于隐式参数的类型,例如x.f()中x的类型,只能在运行期进行绑定。这时候就是动态绑定。通俗说就是不知道X是什么类型的。
每次方法调用时,都会对X类和X类的父类列出一个方法表,每次方法在调用的时候在方法表中进行寻找,因为不确定到底调用的是X类的方法还是X父类的方法。
说明:如果一个方法很假单并且没有被覆盖,编译器就会对此代码进行优化,这个过程为“内联”
例如:内联调用e.getName会被替换为e.name.如果被覆盖,那么就不确定调用方法是哪个,因此就不会进行优化