我们说的绑定理解起来可以这么想,一个方法和那哪个类联系起来,就是我们在调用方法的时候判断调用的这个方法是属于哪个类的,在java面向对象的思想里,多态是个很重要的方面,而静态绑定与动态绑定就是多态的关键,事物的多种形态,也就是要调用哪个方法,执行什么,让一个类拥有什么特点。
Java的绑定有静态绑定和动态绑定,用白话来说:静态绑定,静态的,字面意思是静止的时候就可以判断和哪个绑定了,动态绑定,动起来才能绑定,也就是程序运行起来才能判断绑定什么。
静态绑定:在程序编译的过程中,就可以判断当前调用哪个方法,或者说这个方法属于哪个类。
动态绑定:不像静态绑定在程序编译的时候判断,是在程序运行的时候判断调用哪个类的方法,一般用多态就会用到动态绑定。在程序编译器不知道要调用哪个方法,只有当程序运行起来的时候才发现原来是调用这个。
实现静态绑定一般用final,static和private关键字,至于为什么?根据我的理解用final关键字修饰的类不能被继承,用final关键字修饰的方法不能被重写,没有继承,没有重写谈不上有多态,程序在编译的时候就可以判断方法属于哪个类,调用哪个类的方法。private私有的,用private关键字修饰的属性只属于本类,外界不能访问。在单例模式中我们通过用private修饰构造方法,让外界无法调用单例类的构造方法创建对象。可以说用private修饰的东西和本类绑定在一起了,无论如何也不能属于别的类。对于static关键字,被static修饰的我们称为静态的,静态的变量方法属于类,不属于某个对象,也就是说一个被static修饰的属于一个类,被static修饰的方法能被子类继承得到,但是不能重写(覆盖)虽然也可以通过创建对象进行访问,但是也是属于所在的那个类。
看到关于动态绑定的内部实现机制:http://blog.csdn.net/sureyonder/article/details/5569617,介绍了内存中方法表的概念,方法表是一块连续的内存空间可以说是数组,上面存着指向方法区的方法的指针,但是这个方法表中没有private,static,final关键字修饰的方法,也就是被这三个关键字修饰的方法属于静态绑定。我们写的每个类都会有一个方法表,这个表指向这个类的方法,每个指针和方法一一对应,如果通过继承子类中没有重写(覆盖)这个方法,但是这个方法确实是存在父类中的,那么这个方法在子类的方法表也是存在的,只是这个存在父类中不存在子类中的方法指向的是父类。这样我们运行代码,每个方法通过指针,都会判断出这个方法属于哪个类,具体执行什么。
下面创建父类Father,子类Son继承Father类
package demo_2; public class Son extends Father { @Override public void say() { System.out.println("儿子说话"); } @Override public void sing() { System.out.println("儿子唱歌"); } @Override public void dance() { System.out.println("儿子跳舞"); } public static void main(String[] args) { Father father = new Son(); father.say(); father.run(); } } class Father{ public void say() { System.out.println("爸爸说话"); } public void sing() { System.out.println("爸爸唱歌"); } public void dance() { System.out.println("爸爸跳舞"); } public void run() { System.out.println("爸爸跑步"); } }
父类Father和子类Son的方法所在方法表中的位置一致,各自的方法指向自己的内存区域,我们创建对象时,虚拟机判断创建的哪个对象,上面代码我们创建的是Son类的引用,这时候不知道调用的哪个,接着执行,根据指向的位置虚拟机判断我们调用的方法是哪个类中的方法,
JAVA 虚拟机调用一个类方法时(静态方法),它会基于对象引用的类型(通常在编译时可知)来选择所调用的方法。相反,当虚拟机调用一个实例方法时,它会基于对象实际的类型(只能在运行时得知)来选择所调用的方法,这就是动态绑定,是多态的一种。动态绑定为解决实际的业务问题提供了很大的灵活性,这也是java面向对象的思想。