博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
纳尼?Java种的重载还有静态绑定这种说法?
阅读量:3946 次
发布时间:2019-05-24

本文共 2089 字,大约阅读时间需要 6 分钟。

流量如水,文章就是一个瓶子,标题是瓶口,内容是瓶身。 瓶子装水有多快依赖瓶口大小,瓶子装水有多少依赖瓶身大小。

深入理解Java重载

什么是重载?

在同一个类中,如果多个方法有相同的方法名称,不同的参数类型,参数个数,参数顺序,即称为重载,比如一个类中有多个构造方法。

String 类中的 valueOf 是比较著名的重载案例,它有9个方法,可以将输入的基本数据类型、数组、Object 等转化称为字符串。在编译器的眼里,方法名称+参数列表,组成了一个唯一键,称为方法签名,JVM 通过这个唯一键决定调用哪种重载的方法。注意,方法返回值并非是这个组合体中的一员,所以在使用重载机制时,不能有两个方法名称完全相同,参数类型和个数也相同,但是返回类型不相同的方法,如下实例代码:

public class Student {
public void methodOverload() {
} // 编译出错,返回值并不是方法签名的一部分 public int methodOverload() {
return 7; } // 编译出错,访问修饰符也不是方法签名的一部分 private void methodOverload() {
} // 编译出错,final 修饰符也不是方法签名的一部分 private final void methodOverload() {
} // 编译出错,static 修饰符也不是方法签名的一部分 public static void methodOverload() {
}}

重载的调用规则是什么?

重载似乎是比较容易理解和掌握的编程技能了,有时候仅仅凭借肉眼就能知道应调用哪个重载方法,那么看如下实例代码,如果调用 methodOverload(7) ,猜一下到底调用的是谁呢(JDK11 环境)?

public class OverloadMethods {
// 1.无参方法 public void methodOverload() {
System.out.println("无参方法"); } // 2.基本数据类型 public void methodOverload(int param) {
System.out.println("参数为基本类型 int 的方法"); } // 3.包装数据类型 public void methodOverload(Integer param) {
System.out.println("参数为包装类型 Integer 的方法"); } // 4.可变参数,可以接受 0 ~ n 个 Integer 对象 public void methodOverload(Integer param) {
System.out.println("可变参数方法"); } // 5.Object 对象 public void methodOverload(Object param) {
System.out.println("参数为 Object 的方法"); }}

JVM 在重载方法中,选择合适的目标方法的顺序如下:

  • 精确匹配
  • 如果是基本数据类型,自动转换为更大表示范围的基本类型
  • 通过自动拆箱与装箱
  • 通过子类向上转型继承路线依次匹配
  • 通过可变参数匹配

精确匹配优先,这是无容置疑的,int 在和 Integer 的较量中胜出,因为不需要自动装箱,所以 7 会调用 int 参数的方法。也就是第2种方法,你猜对了吗?如果是 new Integer(7) 的话,Integer 参数的方法胜出。

如果本方法只有 methodOverload(long) ,则可以接收 methodOverload(3) 的实参调用;反之,如果只有 methodOverload(int) ,而传入 long 值,则会编译出错。基本数据类型转化为表示范围更大的基本数据类型优先于自动装箱,即 int 转为 long ,优先于装箱为 Integer ,所以会发生编译错误。
注意,null 可以匹配任何类对象,在查找目标方法时,是从最底层子类依次向上查找的,在本次实例中,如果 methodOverload(null) ,则会调用参数为 Integer 的方法。为什么呢?

1. 因为 Integer 是一个类2. 它是 Object 的子类

在示例代码中,如果还有单个 String 类型参数的方法,则会编译出错,因为 null 不知道该选择 Integer 还是 String。根据上述规则,可变参数的优先级别是最低的,但是如果调用 methodOverload(13,14) ,此时有两个参数,虽然有自动装箱的开销,但可变参数仍然会执行这种方法请求。

父类的共有实例方法与子类的共有实例方法可以存在重载关系。不管继承关系如何复杂,重载在编译时可以根据规则知道调用哪种目标方法。所以,重载又称为静态绑定。

转载地址:http://ksqwi.baihongyu.com/

你可能感兴趣的文章
Android Package and Manifest File
查看>>
Creating Multiple APKs with 2+ Dimensions 创建两种以上屏幕尺寸多apk支持
查看>>
Abstracting the New APIs 抽象出新的API
查看>>
Proxying to the New APIs 代理新的API
查看>>
Creating an Implementation with Older APIs 用较早版本的APIs实现抽象类
查看>>
Using the Version-Aware Component 使用版本识别组件
查看>>
Enhancing Security with Device Management Policies 加强安全与设备管理策略 Developing for Enterprise
查看>>
Advertising without Compromising User Experience 不降低用户体验的广告
查看>>
Planning Screens and Their Relationships 规划屏幕和它们的关系
查看>>
Planning for Multiple Touchscreen Sizes 规划多个触摸屏尺寸
查看>>
Providing Descendant and Lateral Navigation 提供下一代和横向导航
查看>>
GPS 0183协议GGA、GLL、GSA、GSV、RMC、VTG解释 + 数据解析
查看>>
android如何使得电阻屏在第一次开机时自动叫起屏幕校准程序
查看>>
android如何实现:当开启图案解锁时,取消滑动解锁
查看>>
Providing Ancestral and Temporal Navigation 设计高效的应用导航
查看>>
Putting it All Together: Wireframing the Example App 把APP例子用线框图圈起来
查看>>
Implementing Lateral Navigation 实现横向导航
查看>>
Implementing Ancestral Navigation 实现原始导航
查看>>
Implementing Temporal Navigation 实现时间导航
查看>>
Responding to Touch Events 响应触摸事件
查看>>