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");
}
}

执行的结果:

person
person
person

不管在运行的时候传入的实际类型是什么,它永远都只会执行 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");
}
}

结果:

person
man
woman

这种实现方式有一个明显的缺点,它是伪动态的,仍然需要我们来通过程序来判断类型。假如有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");
}
}

java的动态绑定与双分派(规避instanceof)的更多相关文章

  1. 访问者模式讨论篇:java的动态绑定与双分派

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

  2. Java的动态绑定机制

    Java的动态绑定又称为运行时绑定.意思就是说,程序会在运行的时候自动选择调用哪儿个方法. 一.动态绑定的过程: 例子: public class Son extends Father Son son ...

  3. java的动态绑定和多态

    public class Shape { public void area() { System.out.println("各种形状的面积..."); } public stati ...

  4. 关于 java 的动态绑定机制

    关于 java 的动态绑定机制 聊一聊动态绑定机制, 相信看完这篇文章,你会对动态绑定机制有所了解. 网上大多一言概括: 当调用对象的时候,该方法会和该对象的内存地址/运行类型绑定. 当调用对象的属性 ...

  5. Java的动态绑定

    看这段代码 Father father = new Son(); 父类引用指向子类对象,这是java的多态特性,有多态引到动态绑定,如何引入呢,看这个代码: class Father{ private ...

  6. java的动态绑定和静态绑定

    首先是方法的参数是父类对象,传入子类对象是否可行然后引出Parent p = new Children();这句代码不是很理解,google的过程中引出向上转型要理解向上转型又引出了动态绑定从动态绑定 ...

  7. java抽象类,接口(接口定义,实现接口,instanceof运算符,对象转换)

    抽象类 在面向对象的概念中,所有的对象都是通过类来表述的,但并不是所有的类都能够完整的描绘对象,如果一个类中没有包含足够的信息来描绘一类具体的对象,这样的类就是抽象类.抽象类往往用来表征对问题领域进行 ...

  8. Java学习:集合双列Map

    数据结构 数据结构: 数据结构_栈:先进后出 入口和出口在同一侧 数据结构_队列:先进先出 入口和出口在集合的两侧 数据结构_数组: 查询快:数组的地址是连续的,我们通过数组的首地址可以找到数组,通过 ...

  9. java https tomcat 单双认证(含证书生成和代码实现) 原创转载请备注,谢谢O(∩_∩)O

    server: apache-tomcat-6.0.44 jdk1.7.0_79client: jdk1.7.0_79 jks是JAVA的keytools证书工具支持的证书私钥格式. pfx是微软支持 ...

随机推荐

  1. Android 布局之DrawLayout

    在刚开始学android的时候肯定会知道,android的主要的布局就是LinearLayout.RelativeLayout.FramLayout.AbsoluteLayout.以及TableLay ...

  2. 《Numerical Methods》-chaper4-一元非线性方程的解

    在许多生产时间问题中,我们根据已知条件往往会列出一个一元非线性方程,一个最典型的例子就是银行存款的问题,由于其利息需要基于前一年的本息和,因此列出来的方程x的指数往往是高次的.还有物理问题当中一系列用 ...

  3. Spark RDD概念学习系列之Spark Hash Shuffle内幕彻底解密(二十)

    本博文的主要内容: 1.Hash Shuffle彻底解密 2.Shuffle Pluggable解密 3.Sorted Shuffle解密 4.Shuffle性能优化 一:到底什么是Shuffle? ...

  4. Digital Root - SGU 118(高精度运算)

    题目大意:有K组测试数据,然后每组有N个正整数,A1,A2,A3.....An,求出 A1 + A1*A2 + A1*A2*A3 + .......A1*A2*...An 的数根. 分析:有个对9取余 ...

  5. Node.js学习(10)----文件系统fs

    fs 模块是文件操作的封装,它提供了文件的读取.写入.更名.删除.遍历目录.链接等 POSIX 文件系统操作.与其他模块不同的是,fs 模块中所有的操作都提供了异步的和同步的两个版本, 例如读取文件内 ...

  6. Oracle keep详解

    原题目 select * from dept where deptno=(select max(deptno) keep(dense_rank last order by count(1))   fr ...

  7. UVa1608 UVaLive6258 Non-boring sequences

    填坑系列(p.248) 比较神 从两端枚举 最坏复杂度就成O(nlogn)了 #include<cstdio> #include<cstdlib> #include<al ...

  8. Linux系统的Cache工作原理和管理机制

    Linux系统Cache 管理是 Linux 内核中一个很重要并且较难理解的组成部分.本文详细介绍了 Linux 内核中文件 Cache 管理的各个方面,希望能够帮助到你. 操作系统和文件 Cache ...

  9. spring mvc DispatcherServlet详解之四---视图渲染过程

    整个spring mvc的架构如下图所示: 现在来讲解DispatcherServletDispatcherServlet的最后一步:视图渲染.视图渲染的过程是在获取到ModelAndView后的过程 ...

  10. 搬移到GitHub Page啦~

    GitHub: https://github.com/BOT-Man-JL/ Page: https://BOT-Man-JL.github.io/