文章目录
- 前言
- 静态绑定和动态绑定
前言
第一次以博客的方式来记录学习的过程,此前我都习惯用纸笔记录,虽然麻烦,但记得更牢固。
进入正题。之前在学习java继承和多态部分时,遇到了一点小问题:当父类和子类拥有同名属性时,在子类中调用父类该属性的getter方法,为什么得到的依旧是父类属性呢,this指针不是指向当前子类对象吗?以及为什么使用相同的流程测试方法最终调用的确是子类的方法呢?答案就是java的属性属于静态编译,而方法大部分都是运行时绑定。
先来看下面一段代码
代码如下(父类的代码):
public class Father {
public int age ;
public Father() {
age = 15;
}
public int getAge() {
return this.age;
}
public void testDemo() {
this.test();
}
public void test() {
System.out.println("父类的test方法");
}
}
子类的代码:
public class Son extends Father{
public int age;
public Son() {
age = 8;
}
public void test() {
System.out.println("子类的test方法");
}
public static void main(String[] args) {
Son son = new Son();
System.out.println(son.getAge());//15
son.testDemo();//子类的test方法
}
}
可以看到,同样是在父类中使用this指针,属性指向的还是父类自己的属性,而方法却指向的是子类对象的方法。
造成这种结果的原因就是java的绑定规则不同,处理java类中的成员变量时,采用的是静态绑定,而非运行时绑定。
静态绑定和动态绑定
静态绑定:(final、static、private)在程序执行前已经被绑定,也就是说在编译过程中就已经知道这个方法是哪个类的方法,此时由编译器获取其他连接程序实现。属性也采用的静态绑定,这样做的好处有利于我们及时发现错误,而不会等到运行期间才发现。
动态绑定:在运行根据具体对象的类型进行绑定。在对象调用方法时,首先虚拟机通过对象的引用查询java栈中的本地变量表,得到堆中的对象类型数据的地址,从而找到方法区中的对象类型数据 ,然后查询方法表定位到实际类的方法运行。据此得到该对象对应的方法表 ,进而调用方法表中的某个偏移量所指向的方法。
也就是在调用父类方法的时候指针实际还是指向当前子类对象的。