Java 重写(Override)与重载(Overload)

重写(Override)

重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!

重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。

重载(Overload)

重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。

每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。

方法的重写(Overriding)和重载(Overloading)是java多态性的不同表现,重写是父类与子类之间多态性的一种表现,重载可以理解成多态的具体表现形式。

  • (1)方法重载是一个类中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同,则称为方法的重载(Overloading)。
  • (2)方法重写是在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返回值也一样的方法,就称为重写(Overriding)。
  • (3)方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。

——————————————————————————————————————————————————————————————————————

分派

JVM字节码的执行涉及到方法的调用,其中分派调用过程将会解释Java多态特性,

1. 静态分派

首先是一段重载代码:

public class StaticDispatch {

    static abstract class Human{

    }

    static class Man extends Human{

    }

    static class Woman extends Human{

    }

    public void sayHello(Human guy){
System.out.println("Hello, guy!");
} public void sayHello(Man guy){
System.out.println("Hello, gentleman!");
} public void sayHello(Woman guy){
System.out.println("Hello, lady!");
} public static void main(String[] args) {
Human man = new Man();
Human woman = new Woman();
StaticDispatch sr = new StaticDispatch();
sr.sayHello(man);
sr.sayHello(woman);
}
}

与重载有关,代码的执行结果为:

但为什么会选择执行参数类型为Human的重载呢?

Human man = new Man();

在上面那段代码中,Human称为变量的静态类型(static type),Man称为变量的实际类型(actual type), 静态类型和实际类型在程序中都会发生变化,区别是静态类型的变化仅仅发生在使用期,变量本身的静态类型不会发生改变,并且静态类型是编译期可

知的。而实际类型变化的结果只有运行期才可以确定,编译期并不知道变量的实际类型是什么。

例如

//实际类型变化举例
Human man = new Man();
man = new Woman(); //静态类型变化举例
sr.sayHello((Man)man);
sr.sayHello((Woman)woman);

在之前的代码中,方法的接收者已经确定为sr的情况下,使用哪一个重载的版本取决于传入参数的数据类型。但编译器在重载的时候是以参数的静态类型而不是实际类型作为判断依据的。

因此结果就是执行sayHello(Human)作为调用的目标。

2. 动态分派

首先是一段重写代码:

public class Dynamicdispatch {

    static abstract class Human{
protected abstract void sayHello();
}
static class Man extends Human{ @Override
protected void sayHello() {
// TODO Auto-generated method stub
System.out.println("man say hello!");
} }
static class Woman extends Human{ @Override
protected void sayHello() {
// TODO Auto-generated method stub
System.out.println("woman say hello!");
} } public static void main(String[] args) {
Human man = new Man();
Human woman = new Woman();
man.sayHello();
woman.sayHello();
man = new Woman();
man.sayHello();
}
}

代码执行的结果:

现在的问题是虚拟机如何知道要调用什么方法?

可以javap -verbose来反编译输出的信息。

16和20句把创建好的两个对象的引用压到栈顶,这两个对象是将要执行sayHello()方法的所有者,为接收者; 17和21是方法调用指令,这两个指令都指向了#22号,就是Human.sayHello(),但是最终执行的目标方法却是不相同的。

这与invokevirtual指令的运行时解析有关:

  1. 找到操作数栈顶的第一个元素所指向的对象的实际类型;
  2. 如果在该类型中找到与常量中的描述符和简单名称都相同的方法,进行权限访问,通过则返回这个方法的引用;
  3. 否则对该类型的父类进行第二步的搜索和验证;
  4. 如果始终找不到就跑出异常。

由于invokevirtual指令执行的第一步就是在运行期确定接收者的实际类型,所以两次指令都将符号引用解析到了不同的直接引用上去了。这就是重写的本质。

3. 单分派与多分派

静态多分派,动态单分派(到目前为止)

方法的接收者和方法的参数统称为方法的宗量。

静态分派过程中,选择目标方法的依据:静态类型的选择和方法参数的选择

动态分派过程中,选择目标方法的依据:静态类型,因为在动态执行时,编译期已经决定目标方法的签名(参数),所以不会关心传过来的参数。

从JVM字节码执行看重载和重写的更多相关文章

  1. JVM总结(五):JVM字节码执行引擎

    JVM字节码执行引擎 运行时栈帧结构 局部变量表 操作数栈 动态连接 方法返回地址 附加信息 方法调用 解析 分派 –“重载”和“重写”的实现 静态分派 动态分派 单分派和多分派 JVM动态分派的实现 ...

  2. 一夜搞懂 | JVM 字节码执行引擎

    前言 本文已经收录到我的 Github 个人博客,欢迎大佬们光临寒舍: 我的 GIthub 博客 学习导图 一.为什么要学习字节码执行引擎? 代码编译的结果从本地机器码转变为字节码,是存储格式发展的一 ...

  3. JVM 字节码执行实例分析

    前言 最近在看<Java 虚拟机规范>和<深入理解JVM虚拟机>,对于字节码的执行有了进一步的了解.字节码就像是汇编语言,是 JVM 的指令集.下面我们先对 JVM 执行引擎做 ...

  4. 从jvm字节码指令看i=i++和i=++i的区别

    1. 场景的产生 先来看下下面代码展示的两个场景 @Testvoid testIPP() { int i = 0; for (int j = 0; j < 10; j++) { i = i++; ...

  5. 深入理解JVM—字节码执行引擎

    原文地址:http://yhjhappy234.blog.163.com/blog/static/3163283220122204355694/ 前面我们不止一次的提到,Java是一种跨平台的语言,为 ...

  6. JVM字节码执行引擎和动态绑定原理

    1.执行引擎 所有Java虚拟机的执行引擎都是一致的: 输入的是字节码文件,处理过程就是解析过程,最后输出执行结果. 在整个过程不同的数据在不同的结构中进行处理. 2.栈帧 jvm进行方法调用和方法执 ...

  7. jvm 字节码执行 (一)方法调用

    “虚拟机”是一个相对于“物理机”的概念,这两种机器都有代码执行能力,其区别是物理机的执行引擎是直接建立在处理器.硬件.指令集和操作系统层面上,而虚拟机的执行引擎是 由自己实现的,因此可以自行制定指令集 ...

  8. JVM字节码执行引擎

    一.概述 在不同的虚拟机实现里面,执行引擎在执行Java代码的时候可能会有解释执行(通过解释器执行)和编译器执行(通过即时编译器产生本地代码执行)两种选择,所有的Java虚拟机的执行引擎都是一致的:输 ...

  9. jvm 字节码执行 (二)动态类型支持与基于栈的字节码解释执行

    动态类型语言 动态类型语言的关键特征是它的类型检查的主体过程是在运行期而不是编译期. 举例子解释“类型检查”,例如代码: obj.println("hello world"); 假 ...

随机推荐

  1. CSS的常见问题

    1.css的编码风格 多行式:可读性越强,但是CSS文件的行数过多,影响开发速度,增大CSS文件的大小 一行式:可读性稍差,有效减少CSS文件的行数,有利于提高开发速度,减小CSS文件的大小 2.id ...

  2. C language 模拟 win的经典游戏——扫雷

    让我们在terminal下愉快的...扫雷 昨天跟奇葩霖聊起"雷区"这个敏感词汇,然后非常荣幸的... 应该轰炸不到我.. . 后来百无聊赖的去玩了把扫雷.然后发现我之前都是乱扫的 ...

  3. 用R画有图例的中国地图

    近期在网上找了几种画中国地图方法,终于认为这种方法还是最适用的 1.用googlevis包.因为中国国情如今已经不能訪问google地图了.所以大多中国用户来说仅仅能望洋兴叹了. 2.用ggplot包 ...

  4. WPF中展示HTML

    业务需求:将具有表格信息的HTML片段在WPF中展示出来,并像网页端一样,可以进行input的填写,checkbox选择,最后以HTML的形式完成保存. 天真的以为直接引入WPF中的WebBrowse ...

  5. 自学Zabbix3.7.2-事件Event-来源与分类

    一.zabbix 事件从字面理解,就是发生了一个事情就算是一个事件.就在trigger的文章内,我们已经有用到事件,这个事件要讲概念真心不知道怎么说,就拿trigger事件来说,如果trigger从当 ...

  6. 三十天学不会TCP,UDP/IP网络编程-UDP,从简单的开始

    如果对和程序员有关的计算机网络知识,和对计算机网络方面的编程有兴趣,欢迎去gitbook(https://www.gitbook.com/@rogerzhu/)star我的这一系列文章,虽然说现在这种 ...

  7. 封装一个button上带图片的,图片在上,文字在下的按钮

    #import "CJShoppingDetailButton.h" @implementation CJShoppingDetailButton - (void)layoutSu ...

  8. ios 去掉字符串中的空格 和指定的字符

    [问题分析] .使用NSString中的stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]方法只是去掉左右 ...

  9. 童话故事 --- 什么是SQL Server Browser

    高飞狗这几天特别郁闷,不知该如何通过TCP/IP协议连接SQL Server数据库.好在功夫不负有心人,经过几天的刻苦研究,终于得到了答案. 高飞狗呼叫UDP1434端口,"叮铃铃,叮铃铃- ...

  10. js功能代码大全

    1.日期格式化 //化为2017-08-14 function formatDate (date) { var y = date.getFullYear(); var m = date.getMont ...