• 首页
  • 粮食
  • 蔬菜
  • 果品
  • 水产
  • 酒水
  • 饮料
  • 茶叶
  • 畜禽
  • 食用油
  • 资讯
logo
  • 首页>
  • 粮食 >
  • 正文

认识一下Java中方法重载和重写的“真面目”|天天最资讯

2023-05-29 11:36:11 来源:JAVA旭阳
前言

考大家一道题目,下面的类执行结果是什么???

public class DispatcherClient {    public static void main(String[] args) {        Animal a = new Animal();        Animal a1 = new Dog();        Animal a2 = new Cat();        Execute exe = new Execute();        exe.execute(a);        exe.execute(a1);        exe.execute(a2);    }} class Animal {} class Dog extends Animal {} class Cat extends Animal {} class Execute {    public void execute(Animal a) {        System.out.println("Animal");    }    public void execute(Dog d) {        System.out.println("dog");    }    public void execute(Cat c) {        System.out.println("cat");    }}

不知道大家心里的答案是什么?反正我的答案是错的。

正确的答案是:


(相关资料图)

为什么是Animal Animal Animal? 而不是Animal dog cat。

类重载本质——静态分派

execute方法是一个重载方法,本质上就是虚拟机JVM如何确定调用哪个方法执行。在java编译后的class文件中存储的只是方法的符号引用,而不是方法在实际运行过程中内存布局的入口地址(直接引用)。而这个方法从符号引用变成直接引用有两种方式,解析和分派。

解析是发生在类加载的解析阶段就会将一部分方法的符号引用转换为直接引用,比如类的静态方法、私有方法、构造方法、父类方法以及final的方法。我们这里不展开阐述,和本例无关。

而我们方法重载的情况下,java采用的是静态分派的方式确定调用方法。

变量类型

在了解静态分派前我们需要了解下变量的类型。

Animal a1 = new Dog();
静态类型, 也叫做"外观类型", 比如代码中的"Animal", 它的类型是在编译期就知道。实际类型,也叫"运行时类型", 比如代码中的"Dog", 它是在类运行时才会确定,编译期是不知道的。
Execute exe = new Execute();exe.execute(a);exe.execute(a1);exe.execute(a2);

这里多次调用了execute方法,在方法接收者已经确定是对象exe的前提下,使用哪个重载的方法,就完全取决于传入参数的数量和数据类型。虚拟机在重载时是通过参数的静态类型而不是实际类型作为判断依据的。因为静态类型是编译期可知的,所以,在编译阶段,编译器会根据静态类型决定使用哪个重载版本,如下图例子中的字节码,技术在编译的字节码中确定了它调用的重载方法。

类多态本质——动态分派

既然有静态分派,那么是不是有动态分派呢?什么又是动态派呢?

Java语言的一大特性是多态性,所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。

举个简单的例子,比如Human human = flag ? new Man() : new Woman(), human的具体类型是man还是woman在编写代码的时候我们是无法确定,它是由flag这个标记决定,只有在程序运行的时候才能够确定下来,这种让引用变量在运行时绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。

多态在Java中有两种实现形式,分别是继承和接口,子类重写父类或者接口中的方法,现在举个例子。

public class DynamicDispatch {    static abstract class Animal {        protected abstract void eat();    }    static class Cat extends Animal {        @Override        protected void eat() {            System.out.println("我吃鱼");        }    }    static class Dog extends Animal {        @Override        protected void eat() {            System.out.println("我吃骨头");        }    }    public static void main(String[] args) {        Animal cat = new Cat();        Animal dog = new Dog();        cat.eat();        dog.eat();        cat = new Dog();        cat.eat();    }}

运行结果:

这个结果相信和大家想的是一致的,那大家有想过JVM是怎么找到具体的类型执行的呢?我们定义的引用类型就是Animal,JVM是根据什么来找到对应的Cat或者Dog这些具体的实例执行对应的方法呢?

从字节码角度分析

利用idea的Jclasslib插件查看字节码:

0~15行主要是创建Cat对象和Dog对象的字节码指令。17和21行一模一样,指令都是invokevirtual, 参数都是以上的过程中根据方法接收者的实际类型来确定调用那个方法,找不到往父类继续找的过程,其实也就是重写的本质。我们把这种在运行期根据实际类型确定方法执行版本的分派过程叫做动态分派。

** 虚拟机动态分派的实现 **

上面讲述了虚拟即动态分派的过程,那它是怎么实现这一过程的呢?

因为动态分派是执行非常频繁的动作,而且需要在运行时搜索合适的目标方法,基于性能的考虑,java虚拟机采用了一种基础且常见的优化手段—为类型在方法区建立一个需方法表。使用需方法表索引来代替元数据查找以提高性能。

虚方法表中存放着各个方法的实际入口地址。如果某个方法在子类中没有被重写,那子类的虚方法表中的地址入口和父类相同方法的地址入口时一致的,如果子类重写了方法,子类虚方法表中的地址会被替换为指向子类实现版本的入口地址。

总结

总结下,所有依赖静态类型来定位方法执行版本的分派叫做静态分派。静态分派的典型应用就是方法重载,它是在编译阶段确定的,它会选择一个最合适的版本方法进行调用。而动态分派简单来说就是根据变量的动态类型确定执行哪个方法,典型的应用就是方法的重写。

关键词:

    为您推荐

  • 认识一下Java中方法重载和重写的“真面目”|天天最资讯

    粮食2023-05-29
  • 精锻科技:产能利用率目前大概60%+ 后续会继续提升 世界今热点

    果品2023-05-29
  • 环球热消息:宁波儿童公园门票多少?

    果品2023-05-29
  • 从26楼撑伞跳下男童生命体征平稳具体是什么情况_世界热门

    粮食2023-05-29
  • 桑植公安: 为189名农民工追回薪资178万元|世界观焦点

    粮食2023-05-29
  • 高考倒计时,这份考前小提示请收好→_全球速看

    果品2023-05-29
  • 当前热门:儿童节即将来临,东南公益走进洛江虹山乡“彩虹课堂”

    粮食2023-05-29
  • 世界动态:无时不刻的意思?_无时不刻

    果品2023-05-29
  • 中韩翻译器 中韩在线翻译器

    粮食2023-05-29
  • 《速度与激情10》全球票房破5亿 为今年第三高

    果品2023-05-29
  • 老板鱼怎么处理的做法_老板鱼怎么处理|最新快讯

    粮食2023-05-29
  • 当前热议!京西水泉坡持续有人毁林造墓

    果品2023-05-29
  • 天天观热点:感恩的心歌词完整打印_感恩的心歌词完整

    粮食2023-05-29
  • 2023中关村论坛首设女性平行论坛 科技工作者共话“她力量” 热头条

    果品2023-05-29
  • 天天热点评!蓝牙耳机充电电压及电流是多少_蓝牙耳机有电流声小妙招

    粮食2023-05-29
  • 开面馆需要多少钱一家_开面馆需要多少钱-每日热讯

    果品2023-05-29
  • 广元近郊一片绚烂花海,40分钟自驾轻松抵达,人迹稀少! 每日热点

    粮食2023-05-29
  • 元电荷e怎么读(元电荷)

    果品2023-05-29
  • 途安l怎么样值得买吗(途安l)_今日聚焦

    粮食2023-05-29
  • 今日热闻!@太原人!6月1日起,山西电价调整!

    果品2023-05-29

果品

  • 精锻科技:产能利用率目前大概60%+ 后续会继续提升 世界今热点
  • 环球热消息:宁波儿童公园门票多少?
  • 高考倒计时,这份考前小提示请收好→_全球速看
  • 世界动态:无时不刻的意思?_无时不刻
  • 《速度与激情10》全球票房破5亿 为今年第三高

蔬菜

  • 说好“一梯一户”却成了“两梯两户”,买方能否解除合同?
  • 更高水平开放合作助力中国东盟经贸发展迎新机遇
  • 9被告人犯侵犯著作权罪被判刑罚
  • 玉渊谭天丨中美再通话,“建设性”很重要
  • 环球时报社评:中美经贸需要建设性对话
  • 俄媒:莫斯科扩大新冠感染新疗法试点范围
  • 冰雪之约 中国之邀 | 追赶的勇气
  • 中国第20批赴黎维和建筑工兵分队完成“VA-2”道路排水系统修缮任务
  • 中国常驻联合国代表团举办恢复联合国合法席位50周年图片展
  • 美专家认为三大原因导致美国供应链危机

Copyright   2015-2022 亚太食品网 版权所有  备案号:沪ICP备2020036824号-11   联系邮箱: 562 66 29@qq.com