Java方法的静态绑定与动态绑定讲解(向上转型的运行机制详解)

摘要:
final、private和static修改的方法和构造函数是静态绑定的,但不能调用子类中的新方法,编译器通过声明对象的类型(即引用其自己的类型),在方法区域中的类型的方法表中搜索匹配的方法(最佳匹配方法:父类的方法表中没有向子类添加方法。在上述编译阶段,编译器在对象类型声明的方法表搜索方法,使用实例对象调用方法的过程是动态绑定:

   转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6554103.html

    一:绑定

        把一个方法与其所在的类/对象 关联起来叫做方法的绑定。绑定分为静态绑定(前期绑定)和动态绑定(后期绑定)。

   

    二:静态绑定

        静态绑定(前期绑定)是指:在程序运行前就已经知道方法是属于那个类的,在编译的时候就可以连接到类的中,定位到这个方法。

        在Java中,final、private、static修饰的方法以及构造函数都是静态绑定的,不需程序运行,不需具体的实例对象就可以知道这个方法的具体内容。

    三:动态绑定

        动态绑定(后期绑定)是指:在程序运行过程中,根据具体的实例对象才能具体确定是哪个方法。

        动态绑定是多态性得以实现的重要因素,它通过方法表来实现:每个类被加载到虚拟机时,在方法区保存元数据,其中,包括一个叫做 方法表(method table)的东西,表中记录了这个类定义的方法的指针,每个表项指向一个具体的方法代码。如果这个类重写了父类中的某个方法,则对应表项指向新的代码实现处。从父类继承来的方法位于子类定义的方法的前面。

        动态绑定语句的编译、运行原理:我们假设 Father ft=new Son();  ft.say();  Son继承自Father,重写了say()。

        1:编译:我们知道,向上转型时,用父类引用执行子类对象,并可以用父类引用调用子类中重写了的同名方法。但是不能调用子类中新增的方法,为什么呢?

                     因为在代码的编译阶段,编译器通过 声明对象的类型(即引用本身的类型) 在方法区中该类型的方法表中查找匹配的方法(最佳匹配法:参数类型最接近的被调用),如果有则编译通过。(这里是根据声明的对象类型来查找的,所以此处是查找 Father类的方法表,而Father类方法表中是没有子类新增的方法的,所以不能调用。)

                     编译阶段是确保方法的存在性,保证程序能顺利、安全运行。

        2:运行:我们又知道,ft.say()调用的是Son中的say(),这不就与上面说的,查找Father类的方法表的匹配方法矛盾了吗?不,这里就是动态绑定机制的真正体现。

                     上面编译阶段在 声明对象类型 的方法表中查找方法,只是为了安全地通过编译(也为了检验方法是否是存在的)。而在实际运行这条语句时,在执行 Father ft=new Son(); 这一句时创建了一个Son实例对象,然后在 ft.say() 调用方法时,JVM会把刚才的son对象压入操作数栈,用它来进行调用。而用实例对象进行方法调用的过程就是动态绑定:根据实例对象所属的类型去查找它的方法表,找到匹配的方法进行调用。我们知道,子类中如果重写了父类的方法,则方法表中同名表项会指向子类的方法代码;若无重写,则按照父类中的方法表顺序保存在子类方法表中。故此:动态绑定根据对象的类型的方法表查找方法是一定会匹配(因为编译时在父类方法表中以及查找并匹配成功了,说明方法是存在的。这也解释了为何向上转型时父类引用不能调用子类新增的方法:在父类方法表中必须先对这个方法的存在性进行检验,如果在运行时才检验就容易出危险——可能子类中也没有这个方法)。

    四:区分

        程序在JVM运行过程中,会把类的类型信息、static属性和方法、final常量等元数据加载到方法区,这些在类被加载时就已经知道,不需对象的创建就能访问的,就是静态绑定的内容;需要等对象创建出来,使用时根据堆中的实例对象的类型才进行取用的就是动态绑定的内容。

免责声明:文章转载自《Java方法的静态绑定与动态绑定讲解(向上转型的运行机制详解)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇java代码之美(13)--- Predicate详解C#正则表达式匹配“换行\回车”等问题下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

真正掌握vuex的使用方法(三)

接下来咱们继续使用vuex来完成上篇文章的投票实例。大家一定要记住,学习编程这种事一定要慢慢来才会快!所以一定要将代码多敲几遍哦! 目前当前的票数已经可以在页面中渲染出来了!接下来要做的事就是让按钮起到应有的责任:点击对应的按钮让数字加1, 总票数也要加1。很简单,只要给按钮增加一个事件,直接改变其状态即可,代码如下: <div id="app"...

Java10 新特性

一、JDK10 发布   2018年3月21日, Oracle官方宣布Java10正式发布。   需要注意的是 Java 9 和 Java 10 都不是 LTS (Long-Term-Support) 版本。和过去的 Java 大版本升级不同,这两个只有半年左右的开发和维护期。而未来的 Java 11,也就是 18.9 LTS,才是 Java 8 之后第一个...

springboot配置rabbitmq的序列化反序列化格式

SpringBoot封装了rabbitmq中,发送对象和接收对象时,会统一将对象和消息互相转换 会用到MessageConverter转换接口 在发送消息时, 会将Object转换成Message Message createMessage(Object object, MessageProperties messageProperties) 接收消息...

[代码审计]XiaoCms(后台任意文件上传至getshell,任意目录删除,会话固定漏洞)

 0x00 前言 这段时间就一直在搞代码审计了。针对自己的审计方法做一下总结,记录一下步骤。 审计没他,基础要牢,思路要清晰,姿势要多且正。 下面是自己审计的步骤,正在逐步调整,寻求效率最高。 0x01 关于 XiaoCms XiaoCms 企业建站版基于 PHP+Mysql 架构 是一款小巧、灵活、简单、易用的轻量级 cms。能满足各种企业站 博客 等...

C#系列之聊聊.Net Core的InMemoryCache

个人博客:http://www.boydwang.com/2017/12/net-core-in-memory-cache/ 这两天在看.net core的in memory cache,这里记录一下用法,主要涉及MemoryCache的Get/Set/Expire/Flush。首先我们先用dotnet命令创建一个mvc的项目,这里我们将使用post...

(转)Android Studio 增加函数注释模板

此篇文章主要介绍如何在Android Studio中函数如何添加注释,使其和eclipse一样方便的添加注释 Android Studio默认函数注释为 /** * */ 下面方法将要改为如下格式 1 2 3 4 5 /**  *  * @author zony  * @time 15-11-25 下午2:41  */...