绑定指的是:一个方法的调用和方法所在的类关联起来。
绑定分为:
1、静态绑定(又叫做前期绑定)
在程序执行前就已经绑定,即在编译期间就知道这个方法属于哪个类,即编译器就已经绑定。
在java中非常容易理解例子就是:方法中有static、final、private、构造函数。
首先static方法不能被继承,只能被子类隐藏,例如:如果引用类型是父类,会调用父类中的static方法,如果引用类型为子类又会调用子类的static方法,意味着static方法没有被继承,只能通过父类本身被调用。
final方法可以被继承,但是不能被覆盖(即子类可以调用,但是不能重写),子类可以调用此方法,但是都是调用的父类中所定义的那个final方法。由此可以确定这个方法是属于父类的。
private方法,不能被继承,如果不能被继承,意味着也只能被父类所调用。
构造函数,只能在子类中通过super关键字调用,只属于父类。除了这些是静态绑定外,其他的都是动态绑定。
2、动态绑定(又叫做后期绑定)
在运行时根据具体对象类型进行绑定。
若一种语言实现了后期绑定,同时必须提供一些机制,可在运行期间判断对象的类型,并分别调用适当的方法。也就是说,编译器此时依然不知道对象的类型,但方法调用机制能自己去调查,找到正确的方法主体。不同的语言对后期绑定的实现方法是有所区别的。但我们至少可以这样认为:它们都要在对象中安插某些特殊类型的信息。
动态绑定的过程:
Java字节码的执行有两种方式:
1.即时编译方式:解释器先将字节码编译成机器码,然后再执行该机器码。
2.解释执行方式:解释器通过每次解释并执行一小段代码来完成Java字节码程 序的所有操作。
通常采用的是第二种方法。由于JVM规格描述具有足够的灵活性,这使得将字节码翻译为机器代码的工作
具有较高的效率。对于那些对运行速度要求较高的应用程序,解释器可将Java字节码即时编译为机器码,从而很好地保证了Java代码的可移植性和高性能。
以下内容来自互联网:
而动态绑定的典型发生在父类和子类的转换声明之下:3:当程序运行并且使用动态绑定调用方法时,虚拟机必须调用同x所指向的对象的实际类型相匹配的方法版本。
假设实际类型为D(C的子类),如果D类定义了f(String)那么该方法被调用,否则就在D的超类中搜寻方法f(String),依次类推。
JAVA 虚拟机调用一个类方法时(静态方法),它会基于对象引用的类型(通常在编译时可知)来选择所调用的方法。相反,当虚拟机调用一个实例方法时,它会基于对象实际的类型(只能在运行时得知)来选择所调用的方法,这就是动态绑定,是多态的一种。动态绑定为解决实际的业务问题提供了很大的灵活性,是一种非常优美的机制。与方法不同,在处理java类中的成员变量(实例变量和类变量)时,并不是采用运行时绑定,而是一般意义上的静态绑定。所以在向上转型的情况下,对象的方法可以找到子类,而对象的属性(成员变量)还是父类的属性(子类对父类成员变量的隐藏)。
public class Father { protected String name = "父亲属性"; } public class Son extends Father { protected String name = "儿子属性"; public static void main(String[] args) { Father sample = new Son(); System.out.println("调用的属性:" + sample.name); } }结论,调用的成员为父亲的属性。
public class Father { protected String name = "父亲属性"; public String getName() { return name; } } public class Son extends Father { protected String name = "儿子属性"; public String getName() { return name; } public static void main(String[] args) { Father sample = new Son(); System.out.println("调用的属性:" + sample.getName()); } }结果:调用的是儿子的属性
如果想要调用子类中有而父类中没有的方法,需要进行强制类型转换
public class Father { protected String name = "父亲属性"; public String getName() { return name; } } public class Son extends Father { protected String name = "儿子属性"; public String getName() { return name; } public void Play(){ System.out.println("我是爱玩的儿子"); } public static void main(String[] args) { Father sample = new Son(); System.out.println("调用的属性:" + sample.getName()); Son s=(Son)sample; //必须强制类型转换,向下转型 s.Play(); } }多态虽然很奇妙,但是有时很难理解,需要多努力啊;