Java多态中动态绑定原理解析

 更新时间:2019年12月18日 08:58:57   作者:天乔巴夏丶  
这篇文章主要介绍了Java多态中动态绑定原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

这篇文章主要介绍了Java多态中动态绑定原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

多态是面向对象程序设计非常重要的特性,它让程序拥有 更好的可读性和可扩展性。

  • 发生在继承关系中。
  • 需要子类重写父类的方法。
  • 父类类型的引用指向子类类型的对象。

自始至终,多态都是对于方法而言,对于类中的成员变量,没有多态的说法。

一个基类的引用变量接收不同子类的对象将会调用子类对应的方法,这其实就是动态绑定的过程。在理解动态绑定之前,先补充一些概念。

引用变量的类型

引用类型的变量具有两种类型:编译时类型和运行时类型。(也分别叫做声明类型和实际类型)举个简单的例子:

//假设Student类是Person类的子类
Person p = new Student();

编译时类型

  • 也叫声明类型,即由声明变量时的类型所决定。
  • 上式的Person即为引用变量p的编译时类型。

运行时类型

  • 也叫实际类型,即由指向对象的实际类型所决定。
  • 上式的Student即为引用变量p的运行时类型。

方法绑定

将方法调用同方法主体关联起来被称为绑定。

静态绑定

在程序执行前进行绑定,叫做静态绑定,也称作前期绑定。在面向过程的语言中是默认的绑定方式。

在Java中,用private、static和final修饰的方法(static和final之后会做出总结)或构造器能够准确地让编译器调用哪个方法,就是静态绑定(static binding)。

动态绑定

在运行时根据对象的运行时类型进行绑定,叫做动态绑定,也叫做后期绑定。当然在Java中,除了静态绑定的那些方法,其他方法的调用方式就是动态绑定啦。

public class DynamicBinding {
  //Object是所有类的超类,根据向上转型,该方法可以接受任何类型的对象
  public static void test(Object x) {
    System.out.println(x.toString());
  }

  public static void main(String[] args) {
    test(new PrimaryStudent());//Student
    test(new Student());//Student
    test(new Person());//Person
    test(new Object());//java.lang.Object@1b6d3586
  }
}

class Person extends Object {
  @Override
  public String toString() {
    return "Person";
  }
  public void run(){}
  public void count(int a){}
}

class Student extends Person {
  @Override
  public String toString() {
    return "Student";
  }
  public void jump(){}
}

class PrimaryStudent extends Student {
}

四句调用方法的语句中的形参,编译时类型都是Object。注意:引用变量只能调用编译时类型所具有的方法。

它们运行时类型各不相同,所以解释运行器在运行时,会调用它们各自类型中重写的方法。

相同的类型的引用变量,在调用同一个方法时,表现出不同的行为特征,这就是多态最直观的体现吧。

方法表

我们还可以发现,test(new PrimaryStudent());的运行结果是Student,,结果很明显,因为PrimaryStudent类中并没有重写父类的方法,如果采用动态绑定的方式调用方法,虚拟机会首先在本类中寻找适合的方法,如果没有,会一直向父类寻找,直到找到为止。

那么,每次调用时都要向上寻找,时间开销必然会很大。为此虚拟机预先为每个类都创建了方法表,其中列出了所有的方法签名(返回值类型不算)和实际调用的方法,这样子的话,在调用方法时直接查表就可以了。(值得一提的是,如果用super限定调用父类方法,那么将直接在实际类型的父类的表中查找)

下面是Person类的方法表:

Person:
  //下面省略Object方法签名
  //xxx()-> Object.xxx()
  //方法签名->实际调用的方法
  toString()->Person.toString()
  run()->Person.run()
  count(int)->Person(int)

下面是Student类的方法表:

Student:
  //下面省略Object方法签名
  //xxx()-> Object.xxx()
  //方法签名->实际调用的方法
  toString()->Student.toString()
  jump()->Student.jump()
  run()->Person.run()
  count(int)->Person(int)

下面是PrimaryStudent类的方法表(PrimaryStudent类为空,直接继承Student类):

PrimaryStudentt:
  //下面省略Object方法签名
  //xxx()-> Object.xxx()
  //方法签名->实际调用的方法
  toString()->Student.toString()
  jump()->Student.jump()
  run()->Person.run()
  count(int)->Person(int)

因此,在执行test(new PrimaryStudent());语句时,虚拟机将会提取PrimaryStudent的方法表。

虚拟机将会在表中搜索定义toString签名的类。这时虚拟机已经知道需要调用Student类型的toString()方法。

最后,调用方法,完毕。

动态绑定大大提升了程序的可扩展性,比如,我现在要新增一个Teacher类,可以直接让Teacher类继承于Person类,再用

Object类的引用指向Teacher对象,而不用做其他的代码调整,动态绑定自动搞定,就相当舒服。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Java 爬虫服务器被屏蔽的解决方案

    Java 爬虫服务器被屏蔽的解决方案

    这篇文章主要介绍了Java 爬虫服务器被屏蔽的解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-10-10
  • Java案例实现不重复的随机数

    Java案例实现不重复的随机数

    这篇文章主要介绍了Java案例实现不重复的随机数,通过创建Set集合对象,可以使用HashSet也可以使用TreeSet,区别在于TreeSet是排序后的,创建随机数对象,获取一个随机数去重等操作,需要的朋友可以参考一下
    2022-04-04
  • IDEA 单元测试报错:Class not found:xxxx springboot的解决

    IDEA 单元测试报错:Class not found:xxxx springb

    这篇文章主要介绍了IDEA 单元测试报错:Class not found:xxxx springboot的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • MyBatis-Plus雪花算法实现源码解读

    MyBatis-Plus雪花算法实现源码解读

    雪花算法是一种用于生成唯一标识符(ID)的分布式算法,雪花算法的设计目标是在分布式系统中生成全局唯一的ID,同时保证ID的有序性和趋势递增,这篇文章主要介绍了MyBatis-Plus雪花算法实现源码解析,需要的朋友可以参考下
    2023-12-12
  • Spring Boot结合IDEA自带Maven插件如何快速切换profile

    Spring Boot结合IDEA自带Maven插件如何快速切换profile

    IDEA是目前 Java 开发者中使用最多的开发工具,它有着简约的设计风格,强大的集成工具,便利的快捷键,这篇文章主要介绍了Spring Boot结合IDEA自带Maven插件快速切换profile,需要的朋友可以参考下
    2023-03-03
  • AQS(AbstractQueuedSynchronizer)抽象队列同步器及工作原理解析

    AQS(AbstractQueuedSynchronizer)抽象队列同步器及工作原理解析

    AQS是用来构建锁或者其他同步器组件的重量级基础框架及整个JUC体系的基石,通过内置的FIFO对列来完成资源获取线程的排队工作,并通过一个int类型变量表示持有锁的状态,本文给大家详细介绍下AQS抽象队列同步器的相关知识,感兴趣的朋友一起看看吧
    2022-03-03
  • springboot数据库操作图文教程

    springboot数据库操作图文教程

    本文以图文并茂的形式给大家介绍了springboot数据库操作,感兴趣的朋友一起看看吧
    2017-07-07
  • Java日常练习题,每天进步一点点(46)

    Java日常练习题,每天进步一点点(46)

    下面小编就为大家带来一篇Java基础的几道练习题(分享)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧,希望可以帮到你
    2021-08-08
  • hibernate-validator后端表单数据校验的使用示例详解

    hibernate-validator后端表单数据校验的使用示例详解

    这篇文章主要介绍了hibernate-validator后端表单数据校验的使用,hibernate-validator提供的校验方式为在类的属性上加入相应的注解来达到校验的目的,本文结合示例代码给大家介绍的非常详细,需要的朋友可以参考下
    2022-08-08
  • 在@Value注解内使用SPEL自定义函数方式

    在@Value注解内使用SPEL自定义函数方式

    这篇文章主要介绍了在@Value注解内使用SPEL自定义函数方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-02-02

最新评论