博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java的动态绑定与双分派(规避instanceof)
阅读量:5134 次
发布时间:2019-06-13

本文共 3654 字,大约阅读时间需要 12 分钟。

1. 动态绑定的概念

    指程执行期间(而不是在编译期间)判断所引用对象的实际类型,根据其实际的类型调用其相应的方法 .

    例如: 

package org.demo.clone.demo;public class DynamicBound {    public static void main(String[] args) {          Person person = new Man() ;          person.say() ;    }}class Person{    public void say(){} ;}class Man extends Person{    public void say(){        System.out.println("Hey Man");    }}

 

结果:

 

Hey Man

 

    调用的是Person对象中的say方法 但是实际执行的是Man中的方法,这就是动态绑定。 在java语言中,继承中的覆盖就是是动态绑定的,当我们用父类引用实例化子类时,会根据引用的实际类型调用相应的方法

 

2. 静态绑定 

    静态绑定就是指在编译期就已经确定执行哪一个方法。方法的重载(方法名相同而参数不同)就是静态绑定的,重载时,执行哪一个方法在编译期就已经确定下来

package org.demo.demo;public class StaticBound {    public static void main(String[] args) {        OutputName out = new OutputName() ;        Person p = new Person() ;        Person man = new Man() ;        Person woman = new Woman() ;        out.print(p) ;        out.print(man) ;        out.print(woman) ;    }}class Person{}class Man extends Person{    }class Woman extends Person{    }class OutputName{    void print(Person p){        System.out.println("person");    }    void print(Man m){        System.out.println("man");    }    void print(Woman w){        System.out.println("woman");    }}

 

执行的结果: 

personpersonperson

不管在运行的时候传入的实际类型是什么,它永远都只会执行 void print(Person p)这个方法,即 : 重载是静态绑定的

  如果希望使用重载的时候,程序能够根据传入参数的实际类型动态地调用相应的方法,也就是说,我们希望java的重载是动态的,而不是静态的。

但是由于java的重载不是动态绑定,只能通过程序来人为判断,我们一般会使用instanceof操作符来进行类型的判断  代码如下: 

package org.demo.demo;public class StaticBound {    public static void main(String[] args) {        OutputName out = new OutputName() ;        Person p = new Person() ;        Person man = new Man() ;        Person woman = new Woman() ;        out.print(p) ;        out.print(man) ;        out.print(woman) ;    }}class Person{}class Man extends Person{    }class Woman extends Person{    }class OutputName{    void print(Person p){        if(p instanceof Man) print((Man)p);        else if (p instanceof Woman) print((Woman)p);        else  System.out.println("person");    }    void print(Man m){        System.out.println("man");    }    void print(Woman w){        System.out.println("woman");    }}

 

结果: 

personmanwoman

 

 

      这种实现方式有一个明显的缺点,它是伪动态的,仍然需要我们来通过程序来判断类型。假如有100个子类的话,还是这样来实现显然是不合适的

必须通过其他更好的方式实现才行,我们可以使用双分派方式来实现动态绑定

 

3. 使用双分派实现动态绑定

    什么是双分派: 

   

package org.demo.demo;/** * 双分派 */public class DoubleAssign {    public static void main(String[] args) {        A a = new A() ;        a.method02(new B()) ;    }    }class A {    public void method01(){        System.out.println("\t method01");    }    public void method02(B  b ){        b.classMethod01(this) ;    }}class B{    public void classMethod01(A a ){        System.out.println("------classMethod01 start----- ");        a.method01();        System.out.println("------classMethod01 end----- ");    }}

 

 

通过双分派实现动态绑定

package org.demo.demo.foo;/** * 通过双分派实现动态绑定 */public class DoubleAssignForDynamicBound {    public static void main(String[] args) {        OutputName out = new OutputName() ;        Person p = new Person() ;        Person man = new Man() ;        Person woman = new Woman() ;        p.accept(out) ;        man.accept(out) ;        woman.accept(out) ;    }}class Person{    public void accept(OutputName out) {        out.print(this) ;    }}class Man extends Person{    public void accept(OutputName out) {        out.print(this) ;    }}class Woman extends Person{    public void accept(OutputName out) {        out.print(this) ;    }}class OutputName{    void print(Person p){        System.out.println("person");    }    void print(Man m){        System.out.println("man");    }    void print(Woman w){        System.out.println("woman");    }}

 

 

 

 

 

 

 

 

 

 

 

 

转载于:https://www.cnblogs.com/liaokailin/p/3804437.html

你可能感兴趣的文章
tmux的简单快捷键
查看>>
[Swift]LeetCode922.按奇偶排序数组 II | Sort Array By Parity II
查看>>
php match_model的简单使用
查看>>
SIP服务器性能测试工具SIPp使用指导(转)
查看>>
Vue_(组件通讯)子组件向父组件传值
查看>>
STM32单片机使用注意事项
查看>>
032. asp.netWeb用户控件之一初识用户控件并为其自定义属性
查看>>
移动开发平台-应用之星app制作教程
查看>>
leetcode 459. 重复的子字符串(Repeated Substring Pattern)
查看>>
springboot No Identifier specified for entity的解决办法
查看>>
浅谈 unix, linux, ios, android 区别和联系
查看>>
51nod 1428 活动安排问题 (贪心+优先队列)
查看>>
latex for wordpress(一)
查看>>
如何在maven工程中加载oracle驱动
查看>>
Flask 系列之 SQLAlchemy
查看>>
aboutMe
查看>>
【Debug】IAR在线调试时报错,Warning: Stack pointer is setup to incorrect alignmentStack,芯片使用STM32F103ZET6...
查看>>
一句话说清分布式锁,进程锁,线程锁
查看>>
FastDFS使用
查看>>
服务器解析请求的基本原理
查看>>