动态绑定的内幕

  将一个方法调用同一个方法主体连接到一起就称为“绑定”(Binding).
若在程序运行以前执行绑定(由编
译器和链接程序,如果有的话),就叫作“早期绑定”。 
   理解多态的那个程序最令人迷惑不解的地方全与早期绑定有关,因为在只有一个Instrument 句柄的前提下,编译器不知
道具体该调用哪个方法。 
    解决的方法就是“后期绑定”,它意味着绑定在运行期间进行,以对象的类型为基础。后期绑定也叫作“动
态绑定”或“运行期绑定”。若一种语言实现了后期绑定,同时必须提供一些机制,可在运行期间判断对象
的类型,并分别调用适当的方法。也就是说,编译器此时依然不知道对象的类型,但方法调用机制能自己去
调查,找到正确的方法主体。不同的语言对后期绑定的实现方法是有所区别的。但我们至少可以这样认为:
它们都要在对象中安插某些特殊类型的信息。
Java 中绑定的所有方法都采用后期绑定技术,除非一个方法已被声明成final。这意味着我们通常不必决定
是否应进行后期绑定——它是自动发生的。
    为什么要把一个方法声明成final 呢?正如上一章指出的那样,它能防止其他人覆盖那个方法。但也许更重
要的一点是,它可有效地“关闭”动态绑定,或者告诉编译器不需要进行动态绑定。这样一来,编译器就可
为final 方法调用生成效率更高的代码。
 
 
 
动态绑定的内幕: 

       1、编译器检查对象声明的类型和方法名,从而获取所有候选方法。试着把Base类的test注释掉,这时再编译就无法通过。 

       2、重载决策:编译器检查方法调用的参数类型,从候选方法选出唯一的那一个(其间会有隐含类型转化)。如果编译器找到多于一个或者没找到,此时编译器就会报错。试着把Base类的test(byte b)注释掉,这时运行结果是1 1。 

       3、若方法类型为priavte static final ,java采用静态编译,编译器会准确知道该调用哪个方法。 

       4、当程序运行并且使用动态绑定来调用一个方法时,那么虚拟机必须调用对象的实际类型相匹配的方法版本。例子中,b所指向的实际类型是TestOverriding,所以b.test(0)调用子类的test。但是,子类并没有重写test(byte b),所以b.test((byte)0)调用的是父类的test(byte b)。如果把父类的(byte b)注释掉,则通过第二步隐含类型转化为int,最终调用的是子类的test(int i)。 
 
    学习总结:多态性是面向对象编程的一种特性,和方法无关。  
  
      简单说,就是同样的一个方法能够根据输入数据的不同,做出不同的处理,即方法的重载——有不同的参数列表(静态多态性)    
     
      而当子类继承自父类的相同方法,输入数据一样,但要做出有别于父类的响应时,你就要覆盖父类方法,即在子类中重写该方法——相同参数,不同实现动态多态性
      
OOP三大特性:继承,多态,封装。 
public class Base 
{ 
    void test(int i) 
    { 
        System.out.print(i); 
    } 
    void test(byte b) 
    { 
        System.out.print(b); 
    } 
} 
public class TestOverriding extends Base 
{ 
    void test(int i) 
    { 
        i++; 
        System.out.println(i); 
    } 
    public static void main(String[]agrs) 
    {         
        Base b=new TestOverriding();//上转型
        b.test(0); 
        b.test((byte)0); 
    } 
} 
       这时的输出结果是1     0,这是运行时动态绑定的结果。动态绑定
原文地址:https://www.cnblogs.com/gaoxiangde/p/4379914.html