全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

Java的动态绑定与双分派_动力节点Java学院整理

Java的动态绑定

所谓的动态绑定就是指程执行期间(而不是在编译期间)判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。java继承体系中的覆盖就是动态绑定的,看一下如下的代码:

class Father { 
  public void method(){ 
    System.out.println("This is Father's method"); 
  } 
} 
 
class Son1 extends Father{ 
  public void method(){ 
    System.out.println("This is Son1's method"); 
  } 
} 
 
class Son2 extends Father{ 
  public void method(){ 
    System.out.println("This is Son2's method"); 
  } 
} 
 
public class Test { 
  public static void main(String[] args){ 
    Father s1 = new Son1(); 
    s1.method(); 
     
    Father s2 = new Son2(); 
    s2.method(); 
  } 
} 

运行结果如下:

This is Son1's method
This is Son2's method

通过运行结果可以看到,尽管我们引用的类型是Father类型的,但是运行时却是调用的它实际类型(也就是Son1和Son2)的方法,这就是动态绑定。在java语言中,继承中的覆盖就是是动态绑定的,当我们用父类引用实例化子类时,会根据引用的实际类型调用相应的方法。

java的静态绑定

相对于动态绑定,静态绑定就是指在编译期就已经确定执行哪一个方法。在java中,方法的重载(方法名相同而参数不同)就是静态绑定的,重载时,执行哪一个方法在编译期就已经确定下来了。看一下代码:

class Father {} 
class Son1 extends Father{} 
class Son2 extends Father{} 
 
class Execute { 
  public void method(Father father){ 
    System.out.println("This is Father's method"); 
  } 
   
  public void method(Son1 son){ 
    System.out.println("This is Son1's method"); 
  } 
   
  public void method(Son2 son){ 
    System.out.println("This is Son2's method"); 
  } 
} 
 
public class Test { 
  public static void main(String[] args){ 
    Father father = new Father(); 
    Father s1 = new Son1(); 
    Father s2 = new Son2(); 
 
    Execute exe = new Execute(); 
    exe.method(father); 
    exe.method(s1); 
    exe.method(s2); 
  } 
} 

运行结果如下:

This is Father's method
This is Father's method
This is Father's method

在这里,程序在编译的时候就已经确定使用method(Father father)方法了,不管我们在运行的时候传入的实际类型是什么,它永远都只会执行method(Father father)这个方法。也就是说,java的重载是静态绑定的。

instanceof操作符与转型

有时候,我们希望在使用重载的时候,程序能够根据传入参数的实际类型动态地调用相应的方法,也就是说,我们希望java的重载是动态的,而不是静态的。但是由于java的重载不是动态绑定,我们只能通过程序来人为的判断,我们一般会使用instanceof操作符来进行类型的判断。我们要对method(Father father)进行修改,在方法体中判断运行期间的实际类型,修改后的method(Father father)方法如下:

public void method(Father father){ 
  if(father instanceof Son1){ 
    method((Son1)father); 
  }else if(father instanceof Son2){ 
    method((Son2)father); 
  }else if(father instanceof Father){ 
    System.out.println("This is Father's method"); 
  } 
}  

请注意,我们必须把判断是否是父类的条件(也就是判断是否为Father类的条件)放到最后,否则将一律会被判断为Father类,达不到我们动态判断的目的。修改代码后,程序就可以动态地根据参数的实际类型来调用相应的方法了。运行结果如下:

This is Father's method
This is Son1's method
This is Son2's method

但是这种实现方式有一个明显的缺点,它是伪动态的,仍然需要我们来通过程序来判断类型。假如Father有100个子类的话,还是这样来实现显然是不合适的。必须通过其他更好的方式实现才行,我们可以使用双分派方式来实现动态绑定。

用双分派实现动态绑定

首先,什么是双分派?

类A中的方法method1和method2的区别就是,method2是双分派。我们可以看一下java双分派的特点:首先要有一个访问类B,类B提供一个showA(A a) 方法,在方法中,调用类A的method1方法,然后类A的method2方法中调用类B的showA方法并将自己作为参数传给showA。双分派的核心就是这个this对象。说到这里,我们已经明白双分派是怎么回事了,但是它有什么效果呢?就是可以实现方法的动态绑定,我们可以对上面的程序进行修改,代码如下:

class Father { 
  public void accept(Execute exe){ 
    exe.method(this); 
  } 
} 
class Son1 extends Father{ 
  public void accept(Execute exe){ 
    exe.method(this); 
  } 
} 
class Son2 extends Father{ 
  public void accept(Execute exe){ 
    exe.method(this); 
  } 
} 
 
class Execute { 
  public void method(Father father){ 
    System.out.println("This is Father's method"); 
  } 
   
  public void method(Son1 son){ 
    System.out.println("This is Son1's method"); 
  } 
   
  public void method(Son2 son){ 
    System.out.println("This is Son2's method"); 
  } 
} 
 
public class Test { 
  public static void main(String[] args){ 
    Father father = new Father(); 
    Father s1 = new Son1(); 
    Father s2 = new Son2(); 
 
    Execute exe = new Execute(); 
    father.accept(exe); 
    s1.accept(exe); 
    s2.accept(exe); 
  } 
} 

可以看到我们修改的地方,在Father,Son1,Son2中分别加入一个双分派的方法。调用的时候,原本是调用Execute的method方法,现在改为调用Father的accept方法。运行结果如下:

This is Father's method
This is Son1's method
This is Son2's method

运行结果符合我们的预期,实现了动态绑定。双分派实现动态绑定的本质,就是在重载方法委派的前面加上了继承体系中覆盖的环节,由于覆盖是动态的,所以重载就是动态的了,与使用instanceof操作符的效果是一样的(用instanceof操作符可以实现重载方法动态绑定的原因也是因为instanceof操作符是动态的)。但是与使用instanceof操作符实现动态绑定相比,双分派方式的可扩展性要好的多。


# Java动态绑定与双分派  # 静态分派与动态分派  # java动态绑定和静态绑定用法实例详解  # 浅谈Java中的重载  # 重写  # 多态  # 静态绑定、动态绑定  # Java 静态绑定与动态绑定深入分析  # 理解Java中的静态绑定和动态绑定  # 详解Java多态对象的类型转换与动态绑定  # Java中的静态绑定和动态绑定详细介绍  # java实现通过绑定邮箱找回密码功能  # JavaFx UI控件与代码间的绑定方法  # Java多态中动态绑定原理解析  # 绑定  # 看一下  # 我们可以  # 可以看到  # 可以实现  # 来实现  # 就是指  # 判断是否  # 也就是说  # 有什么  # 是在  # 在这里  # 子类  # 上了  # 这就是  # 要有  # 说到  # 它是  # 而不  # 只会 


相关文章: 简易网站制作视频教程,使用记事本编写一个简单的网页html文件?  如何在西部数码注册域名并快速搭建网站?  建站之星安装路径如何正确选择及配置?  高端网站建设与定制开发一站式解决方案 中企动力  如何在Golang中指定模块版本_使用go.mod控制版本号  制作网站的网址是什么,请问后缀为.com和.com.cn还有.cn的这三种网站是分别是什么类型的网站?  如何用花生壳三步快速搭建专属网站?  如何在阿里云高效完成企业建站全流程?  如何用虚拟主机快速搭建网站?详细步骤解析  简历在线制作网站免费,免费下载个人简历的网站是哪些?  家族网站制作贴纸教程视频,用豆子做粘帖画怎么制作?  建站之星展会模版如何一键下载生成?  商务网站制作工程师,从哪几个方面把握电子商务网站主页和页面的特色设计?  建站之星价格显示格式升级,你的预算足够吗?  头像制作网站在线观看,除了站酷,还有哪些比较好的设计网站?  官网自助建站系统:SEO优化+多语言支持,快速搭建专业网站  如何优化Golang Web性能_Golang HTTP服务器性能提升方法  制作假网页,招聘网的薪资待遇,会有靠谱的吗?一面试又各种折扣?  如何通过智能用户系统一键生成高效建站方案?  韩国代理服务器如何选?解析IP设置技巧与跨境访问优化指南  如何选择适合PHP云建站的开源框架?  如何有效防御Web建站篡改攻击?  北京网页设计制作网站有哪些,继续教育自动播放怎么设置?  上海制作企业网站有哪些,上海有哪些网站可以让企业免费发布招聘信息?  电影网站制作价格表,那些提供免费电影的网站,他们是怎么盈利的?  c++怎么编写动态链接库dll_c++ __declspec(dllexport)导出与调用【方法】  如何选择高效便捷的WAP商城建站系统?  手机钓鱼网站怎么制作视频,怎样拦截钓鱼网站。怎么办?  平台云上自主建站:模板化设计与智能工具打造高效网站  如何在Windows 2008云服务器安全搭建网站?  如何自定义建站之星网站的导航菜单样式?  深圳网站制作案例,网页的相关名词有哪些?  建站之星微信建站一键生成小程序+多端营销系统  如何快速生成橙子建站落地页链接?  香港服务器如何优化才能显著提升网站加载速度?  小捣蛋自助建站系统:数据分析与安全设置双核驱动网站优化  如何用AWS免费套餐快速搭建高效网站?  手机怎么制作网站教程步骤,手机怎么做自己的网页链接?  测试制作网站有哪些,测试性取向的权威测试或者网站?  如何在阿里云虚拟机上搭建网站?步骤解析与避坑指南  b2c电商网站制作流程,b2c水平综合的电商平台?  如何选择美橙互联多站合一建站方案?  已有域名如何快速搭建专属网站?  建站之星免费模板:自助建站系统与智能响应式一键生成  建站之星×万网:智能建站系统+自助建站平台一键生成  建站之星如何助力网站排名飙升?揭秘高效技巧  定制建站流程解析:需求评估与SEO优化功能开发指南  如何制作新型网站程序文件,新型止水鱼鳞网要拆除吗?  如何将凡科建站内容保存为本地文件?  中山网站制作网页,中山新生登记系统登记流程? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。