轻松理解java前期绑定(静态绑定)与后期绑定(动态绑定) 的区别。

短命女 2023-06-18 04:52 131阅读 0赞

理论概念:(乍一看有些晦涩,建议先看代码再看概念~~)

以下是《java编程思想》原句摘抄:

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

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

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

代码实例:

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

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

  1. /**
  2. * @author XIAOHANG
  3. * @date 2019/8/23
  4. * @description 前期绑定(静态绑定)与后期绑定(动态绑定) 的区别。
  5. */
  6. public class 动态绑定 {
  7. public static void main(String args[]){
  8. 动态绑定 d = new 动态绑定();
  9. d.invoke(new Son());
  10. }
  11. public void invoke(Father f) {
  12. f.play_static();
  13. //f.play_private(); 无法访问父类的private方法,编译器报错。
  14. f.play_final();
  15. f.play_other();
  16. }
  17. }
  18. class Father{
  19. public String name = "Father";
  20. static void play_static() {
  21. System.out.println("Father play");
  22. }
  23. final void play_final() {
  24. System.out.println("Father play");
  25. }
  26. private void play_private() {
  27. System.out.println("Father play");
  28. }
  29. void play_other() {
  30. System.out.println("Father play");
  31. }
  32. }
  33. class Son extends Father{
  34. public String name = "Son";
  35. static void play_static() {
  36. System.out.println("Son play");
  37. }
  38. /*final void play_final() { // 无法重写父类的final方法, 否则编译器标错。
  39. System.out.println("Son play");
  40. }*/
  41. private void play_private() {
  42. System.out.println("Son play");
  43. }
  44. void play_other() {
  45. System.out.println("Son play");
  46. }
  47. }

输出:

  1. Father play
  2. Father play
  3. Son play

#

解释:

这里要注意的是我们的public void invoke(Father f)这个方法,它接收的是一个Father类型的参数,但是呢,我们在调用这个方法的时候,却这样

  1. 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。

这是最直观的动态绑定与静态绑定的区别的体现。

欢迎大家提问拍砖!

发表评论

表情:
评论列表 (有 0 条评论,131人围观)

还没有评论,来说两句吧...

相关阅读

    相关 C++动态静态

    为了支持c++的多态性,才用了动态绑定和静态绑定。理解他们的区别有助于更好的理解多态性,以及在编程的过程中避免犯错误。 需要理解四个名词: 1、对象的静态类型:对象在

    相关 动态静态

    为了支持c++的多态性,才用了动态绑定和静态绑定。理解他们的区别有助于更好的理解多态性,以及在编程的过程中避免犯错误,需要理解四个名词: 1、对象的静态类型:对象在声明时采