为了账号安全,请及时绑定邮箱和手机立即绑定

Java分派

标签:
Java

 Java的重载和重写在开发中是非常常见的,那么它们在Java虚拟机中是如何实现的?先看下Java的两种分派方式:静态分派和动态分派。

一、静态分派

先看一段代码。代码结构如下,很简单的继承关系,各个类也没有属性和方法。
https://img1.sycdn.imooc.com//5b165e590001e14705700214.jpg

代码如下:

复制代码

 1 public class Human { 2    3 } 4  5 public class Man extends Human { 6  7 } 8  9 public class Woman extends Human {10 11 }12 13 //主要的操作类14 public class StaticCall {15 16   public void sayHello(Human person) {17     System.out.println("human hello!");18   }19 20   public void sayHello(Man person) {21     System.out.println("man hello!");22   }23 24   public void sayHello(Woman person) {25     System.out.println("woman hello!");26   }27 28   public static void main(String[] args) {29     StaticCall staticCall = new StaticCall();30 31     Human human = new Human();32     staticCall.sayHello(human);33 34     Human man = new Man();35     staticCall.sayHello(man);36 37     Human woman = new Woman();38     staticCall.sayHello(woman);39   }40 41 }

复制代码

主要看下操作类代码。重载了3个方法,接收的参数类型不同,但是类型是上下级关系。调用时定义了3种类型。

执行的结果是什么呢?

https://img1.sycdn.imooc.com//5b165e65000138c205460470.jpg

如果没有深入的分析,对这个结果可能会有些惊讶,为什么3次的调用结果一样?

先看下几个概念。

" cdata_tag="style">

Human man = new Man();

  Human称为变量的静态类型,或者叫做外观类型,后面的Man被称为变量的实际类型。方法的重载是通过参数的静态类型作为判断的,并且静态类型是编译器可知的,因此在编译阶段编译器会根据参数的静态类型决定使用哪个重载版本。

  再看上面的代码,定义的3个变量的静态类型都是Human类型,所以都选择了sayHello(Human person)作为调用目标。

依赖静态类型来定位方法执行版本的分派动作称为静态分派。静态分派的典型应用就是方法重载。

  另一个问题,是编译器虽然能确定出方法的重载版本,但是在很多情况下这个重载版本并不是唯一的,只能确定一个更加合适的版本。例如,重载的方法中,参数列表除了参数类型不一样,其他都一样,例接收的参数有char\int\long等,传入参数‘a’,则会调用需要char类型参数的方法,去掉需要char类型参数的方法,则会调用需要int类型参数的方法。这时发生了一次自动类型转换。同样,去掉需要int类型参数的方法,则会调用需要long类型参数的方法。这里再次发生类型转换,会按照char->int->long->float->double转换类型。

二、动态分派

  动态分派和重写联系密切。再看下面的代码

https://img1.sycdn.imooc.com//5b165e730001588d05860220.jpg

父类Human定义类sayHello方法,之类重写了该方法。详细代码如下:

复制代码

 1 public class Human { 2   public void sayHello() { 3     System.out.println("hello,human!"); 4   } 5 } 6  7 public class Man extends Human { 8   @Override 9   public void sayHello() {10     System.out.println("hello,Man!");11   }12 }13 14 public class Woman extends Human {15   @Override16   public void sayHello() {17     System.out.println("hello,Woman!");18   }19 }20 21 //主要操作类22 public class DynamicCall {23 24   public static void main(String[] args) {25     Human human = new Human();26     human.sayHello();27 28     Human man = new Man();29     man.sayHello();30 31     Human woman = new Woman();32     woman.sayHello();33   }34 35 }

复制代码

定义了3个类,调用3个类的方法。结果是:

https://img1.sycdn.imooc.com//5b165e7d0001810305060447.jpg

Java是通过变量的实际类型在运行期确定执行哪个版本。上面3个变量的实际类型不同,会调用各自的方法。

原文出处


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消