文章目录

  • 前言
  • 静态绑定和动态绑定

前言

第一次以博客的方式来记录学习的过程,此前我都习惯用纸笔记录,虽然麻烦,但记得更牢固。
进入正题。之前在学习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栈中的本地变量表,得到堆中的对象类型数据的地址,从而找到方法区中的对象类型数据 ,然后查询方法表定位到实际类的方法运行。据此得到该对象对应的方法表 ,进而调用方法表中的某个偏移量所指向的方法。

也就是在调用父类方法的时候指针实际还是指向当前子类对象的。