【转载】轻松理解java前期绑定(静态绑定)与后期绑定(动态绑定) 的区别

理论概念:
 以下是《java编程思想》原句摘抄:

程序绑定的概念:
绑定指的是一个方法的调用与方法所在的类(方法主体)关联起来。对java来说,绑定分为前期绑定(静态绑定)与后期绑定(动态绑定)。

静态绑定:
在程序执行前方法已经被绑定(也就是说在编译过程中就已经知道这个方法到底是哪个类中的方法),此时由编译器或其它连接程序实现。
针对java简单的可以理解为程序编译期的绑定;这里特别说明一点,java当中的方法只有final,static,private和构造方法是前期绑定

动态绑定:
后期绑定:在运行时根据具体对象的类型进行绑定
若一种语言实现了后期绑定,同时必须提供一些机制,可在运行期间判断对象的类型,并分别调用适当的方法。也就是说,编译器此时依然不知道对象的类型,但方法调用机制能自己去调查,找到正确的方法主体。不同的语言对后期绑定的实现方法是有所区别的。但我们至少可以这样认为:它们都要在对象中安插某些特殊类型的信息。

代码实例:
类 动态绑定  :测试类,主要看它的invoke(Father f)方法,该方法接收一个父类的引用,并在其中调用父类f的方法。

类 Father 和 Son  :父类与子类,父类有static、final、private、普通(other)、四种不同类型的方法,而子类Son都对这些方法进行了重写,(除了父类中的final方法,final方法不可以被子类重写,否则就报错)。
 

/**
 * @author XIAOHANG
 * @date 2019/8/23
 * @description 前期绑定(静态绑定)与后期绑定(动态绑定) 的区别。
 */
public class 动态绑定 {
    public static void main(String args[]){
        动态绑定 d = new 动态绑定();
        d.invoke(new Son());
    }
 
    public void invoke(Father f) {
        f.play_static();
        //f.play_private(); 无法访问父类的private方法,编译器报错。
        f.play_final();
        f.play_other();
    }
}
 
class Father{
    public String name = "Father";
 
    static void play_static() {
        System.out.println("Father play");
    }
 
    final void play_final() {
        System.out.println("Father play");
    }
 
    private void play_private() {
        System.out.println("Father play");
    }
 
    void play_other() {
        System.out.println("Father play");
    }
}
 
class Son extends Father{
    public String name = "Son";
 
    static void play_static() {
        System.out.println("Son play");
    }
 
    /*final void play_final() {  // 无法重写父类的final方法, 否则编译器标错。
        System.out.println("Son play");
    }*/
 
    private void play_private() {
        System.out.println("Son play");
    }
 
    void play_other() {
        System.out.println("Son play");
    }
}

OUTPUT:

Father play
Father play
Son play

        解释:
        这里要注意的是我们的public void invoke(Father f)这个方法,它接收的是一个Father类型的参数,但是呢,我们在调用这个方法的时候,却这样d.invoke(new Son());
我们向它传入了一个Son对象!这样可以吗?这样是可以的,这就是java向上转型带来的好处:子类可以当做父类用。编译器在调用invoke方法时实际上是这么处理传入参数的:Father f = new Son();父类引用指向子类对象!那么在invoke方法中我们调用 f 的方法的时候到底是调用Son的,还是调用Father的呢?

        这就是动态绑定的神奇之处,如果我们调用的是 f 的static、final、private这三种方法(红字与文章开头的红字对应),就是使用了静态绑定,虽然传入的是Son对象,但调用的仍是父类的方法,所以输出两个Father play,但如果我们调用的不是这三种方法(比如other方法),那我们使用的就是动态绑定,这时候我们调用的就是子类重写父类的方法play_other(),所以输出的是Son play。

       这是最直观的动态绑定与静态绑定的区别的体现。
————————————————
版权声明:本文为CSDN博主「请保持优秀。」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/IT_TIfarmer/article/details/103321668

发布了42 篇原创文章 · 获赞 23 · 访问量 8275

猜你喜欢

转载自blog.csdn.net/Andrew_Zeng/article/details/104204659