码出高效:Java开发手册-第2章(10)

简介: 本章开始讲解面向对象思想,并以Java 为载体讲述面向对象思想在具体编程语言中的运用与实践。当前主流的编程语言有50 种左右,主要分为两大阵营:面向对象编程与面向过程编程。面向对象编程(Object-Oriented Programming,OOP)是划时代的编程思想变革,推动了高级语言的快速发展和工业化进程。OOP 的抽象、封装、继承、多态的理念使软件大规模化成为可能,有效地降低了软件开发成本、维护成本和复用成本。面向对象编程思想完全不同于传统的面向过程编程思想,使大型软件的开发就像搭积木一样隔离可控、高效简单,是当今编程领域的一股势不可......

2.5 重载

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

public class SameMethodSignature {

      public void methodForOverload() {}

      // 编译出错。返回值并不是方法签名的一部分

      public int methodForOverload() {

             return 7;

      }

      // 编译出错。访问控制符也不是方法签名的一部分

      private void methodForOverload() {}

      // 编译出错。静态标识符也不是方法签名的一部分

      public static void methodForOverload() {}

      // 编译出错。final 标识符也不是方法签名的一部分

      private final void methodForOverload() {}

}

      重载似乎是比较容易理解和掌握的编程技能,有时仅凭肉眼判断就能知道应调用哪种重载方法,特别是如下代码所示的第一种方法和第二种方法。前者是无参的,后者参数是int param,但是后边的三种方法,只是参数类型不同罢了。这时,如果调用methodForOverload(7),猜猜,到底调用的是谁呢(JDK11 环境)?

public class OverloadMethods {

      // 第一种方法:无参

      public void overloadMethod() {

             System.out.println(" 无参方法");

      }

      // 第二种方法:基本数据类型

      public void methodForOverload(int param) {

             System.out.println(" 参数为基本类型int 的方法");

      }

      // 第三种方法:包装数据类型

      public void methodForOverload(Integer param) {

             System.out.println(" 参数为包装类型Integer 的方法");

      }

      // 第四种方法:可变参数,可以接受0 ~ n 个Integer 对象

      public void methodForOverload(Integer... param) {

             System.out.println(" 可变参数方法");

      }

      // 第五种方法:Object 对象

      public void methodForOverload(Object param) {

             System.out.println(" 参数为Object 的方法");

      }

}

      先看这五种方法对应的字节签名有何异同点。

// V 表示Void 返回值

public overloadMethod()V

// I 就是代表int 基本数据类型,而非Integer

public methodForOverload(I)V

// L 表示输入参数是对象,然后跟着package+ 类名 (第1处)

public methodForOverload(Ljava/lang/Integer;)V

// varargs 表示可变参数 (第2处)

public varargs methodForOverload([Ljava/lang/Integer;]V

// L 同样表示对象参数

public methodForOverload(Ljava/lang/Object;)V

      第1处与第2处的区别是后者加了varargs 标识,即可变参数,参数个数可以是0或多个,也就是说,它和第1、2、3 个方法都是有可能争抢地盘的。首先,如果调用methodForOverload(),假如在无参方法缺席的情况下,也会调用到可变参数方法。但是如果无参方法在场,就不需要可变参数方法了。现在对这个类来说,methodForOverload(7) 到底花落谁家? JVM 在重载方法中,选择合适的目标方法的顺序如下:

(1)精确匹配。

      (2)如果是基本数据类型,自动转换成更大表示范围的基本类型。

      (3)通过自动拆箱与装箱。

      (4)通过子类向上转型继承路线依次匹配。

      (5)通过可变参数匹配。

      精确匹配优先,这是毫无疑问的。int 在和Integer 的较量中胜出,因为不需要自动装箱,所以7 会调用int 参数的方法。如果是new Integer(7) 的话,Integer 参数的方法胜出。

      如果本方法只有methodForOverload(long),则可以接收methodForOverload(3) 的实参调用;反之,如果只有methodForOverload(int),而传入long 值,则会编译出错。基本数据类型转化为表示范围更大的基本数据类型优先于自动装箱,即int 转为long,优先于装箱为Integer。

      注意,null 可以匹配任何类对象,在查找目标方法时,是从最底层子类依次向上查找的。在本例中,如果methodForOverload(null),则会调用参数为Integer 的方法。第一,因为Integer 是一个类;第二,它是Object 的子类。在示例代码中,如果还有单个String 类型参数的方法,则会编译出错,因为null 不知道该选择Integer,还是String。

      根据上述匹配顺序, 可变参数在竞争中明显处于弱势地位。如果调用methodForOverload(13,14),此时有两个参数,虽然有自动装箱的开销,但可变参数仍会执行这种方法请求。

      最后,有些程序员好奇心特别强,刚才不是说7 是匹配基本数据类型优先,而new Integer(7) 是匹配包装类优先的,那如果这样定义:

public void methodForOverload(int param1, Integer param2) {}

public void methodForOverload(Integer param3, int param4) {}

      这种定义方式就是在考验编译器的忍耐底线, 虽然编译器的内心是崩溃的, 但是这样定义是可以编译通过的, 这也是一种重载方式。但此时调用methodForOverload(13,14) 会彻底让编译器失控,如图2-9 所示。

1.jpg

图2-9 相似重载方法调用出错

      我们设想一下假如输入参数为7,一个类中只有methodForOverload(Object param)和methodForOverload(Integer... param) 两种方法, 根据目标方法匹配顺序,methodForOverload(7) 先自动装箱,然后向上转型,遇到Object。这个规则优先于调用可变参数的重载方法。

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



相关文章
|
2月前
|
Java
Java开发实现图片URL地址检验,如何编码?
【10月更文挑战第14天】Java开发实现图片URL地址检验,如何编码?
79 4
|
15天前
|
Java API Maven
如何使用Java开发抖音API接口?
在数字化时代,社交媒体平台如抖音成为生活的重要部分。本文详细介绍了如何用Java开发抖音API接口,从创建开发者账号、申请API权限、准备开发环境,到编写代码、测试运行及注意事项,全面覆盖了整个开发流程。
58 10
|
2月前
|
监控 Java 测试技术
Java开发现在比较缺少什么工具?
【10月更文挑战第15天】Java开发现在比较缺少什么工具?
36 1
|
2月前
|
Java
Java开发实现图片地址检验,如果无法找到资源则使用默认图片,如何编码?
【10月更文挑战第14天】Java开发实现图片地址检验,如果无法找到资源则使用默认图片,如何编码?
62 2
|
22天前
|
SQL 安全 Java
安全问题已经成为软件开发中不可忽视的重要议题。对于使用Java语言开发的应用程序来说,安全性更是至关重要
在当今网络环境下,Java应用的安全性至关重要。本文深入探讨了Java安全编程的最佳实践,包括代码审查、输入验证、输出编码、访问控制和加密技术等,帮助开发者构建安全可靠的应用。通过掌握相关技术和工具,开发者可以有效防范安全威胁,确保应用的安全性。
44 4
|
23天前
|
缓存 监控 Java
如何运用JAVA开发API接口?
本文详细介绍了如何使用Java开发API接口,涵盖创建、实现、测试和部署接口的关键步骤。同时,讨论了接口的安全性设计和设计原则,帮助开发者构建高效、安全、易于维护的API接口。
57 4
|
1月前
|
开发框架 JavaScript 前端开发
HarmonyOS UI开发:掌握ArkUI(包括Java UI和JS UI)进行界面开发
【10月更文挑战第22天】随着科技发展,操作系统呈现多元化趋势。华为推出的HarmonyOS以其全场景、多设备特性备受关注。本文介绍HarmonyOS的UI开发框架ArkUI,探讨Java UI和JS UI两种开发方式。Java UI适合复杂界面开发,性能较高;JS UI适合快速开发简单界面,跨平台性好。掌握ArkUI可高效打造符合用户需求的界面。
91 8
|
29天前
|
SQL Java 程序员
倍增 Java 程序员的开发效率
应用计算困境:Java 作为主流开发语言,在数据处理方面存在复杂度高的问题,而 SQL 虽然简洁但受限于数据库架构。SPL(Structured Process Language)是一种纯 Java 开发的数据处理语言,结合了 Java 的架构灵活性和 SQL 的简洁性。SPL 提供简洁的语法、完善的计算能力、高效的 IDE、大数据支持、与 Java 应用无缝集成以及开放性和热切换特性,能够大幅提升开发效率和性能。
|
29天前
|
存储 Java 关系型数据库
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践,包括连接创建、分配、复用和释放等操作,并通过电商应用实例展示了如何选择合适的连接池库(如HikariCP)和配置参数,实现高效、稳定的数据库连接管理。
52 2
|
29天前
|
监控 Java 数据库连接
在Java开发中,数据库连接管理是关键问题之一
在Java开发中,数据库连接管理是关键问题之一。本文介绍了连接池技术如何通过预创建和管理数据库连接,提高数据库操作的性能和稳定性,减少资源消耗,并简化连接管理。通过示例代码展示了HikariCP连接池的实际应用。
20 1