深入构造器(2):构造器的重载与相互调用

    技术2022-07-10  134

    前言:同一个类里具有多个构造器,多个构造器的形参列表不同,即被称为构造器重載。构造器重载允许 Java 类里包含多个初始化逻辑,从而允许使用不同的构造器来初始化 Java 对象。在看本篇之前先了解 使用构造器执行初始化 。


    文章目录

    1、构造器的重载1.1、代码表示1.2、运行结果 2、构造器间的相互调用2.1、代码表示2.2、运行结果 3、知识补充3.1、为什么要用 this 来调用构造器,而不是直接复制代码?

    1、构造器的重载

    ​ 构造器重载和方法重载基本相似:概况起来就是名称相同,参数列表不同。要求构造器的名字相同,这一点无须特别要求,因为构造器必须与类名相同,所以同一个类的所有构造器名肯定相同。为了让系统能区分不同的构造器,多个构造器的参数列表必须不同。

    1.1、代码表示

    public class ConstructorOverload { public String name; public int count; /** * 提供无参数的构造器 */ public ConstructorOverload() { } /** * 提供一个参数的构造器,对构造器返回的对象进行初始化 * * @param name 名称 */ public ConstructorOverload(String name) { this.name = name; } /** * 提供两个参数的构造器,对构造器返回的对象进行初始化 * * @param name 名称 * @param count 数量 */ public ConstructorOverload(String name, int count) { this.name = name; this.count = count; } public static void main(String[] args) { // 通过无参数的构造器创建 ConstructorOverload 对象 ConstructorOverload con1 = new ConstructorOverload(); // 通过一个参数的构造器创建 ConstructorOverload 对象 ConstructorOverload con2 = new ConstructorOverload("西瓜"); // 通过两个参数构造器创建 ConstructorOverload 对象 ConstructorOverload con3 = new ConstructorOverload("玉米", 100); // 开始调用方法 System.out.println("名称:" + con1.name); System.out.println("名称:" + con2.name); System.out.println("名称:" + con3.name + "\t 数量:" + con3.count); } }

    1.2、运行结果

    名称:null 名称:西瓜 名称:玉米 数量:100

    2、构造器间的相互调用

    ​ 上面的 ConstructorOverload 类提供了两个重载的构造器,两个构造器的名字相同,但形参列表不同。系统通过 new 调用构造器时,系统将根据传入的实参列表来决定调用哪个构造器。如果系统中包含多个构造器,其中一个构造器的执行体里完全包含另一个构造器的执行体,如下图所示:

    ​ 从图中可以看出,构造器 B 完全包含了构造器 A 。对于这种完全包含的情况分两种:

    方法之间:如果是两个方法之间存在这种关系,则可在方法 B 中直接调用方法 A 。

    构造器之间:构造器不能直接被调用,构造器必须使用 new关键字来调用。但一旦使用 new 关键字来调用构造器,将会导致系统重新创建一个对象。

    2.1、代码表示

    ​ 为了在构造器 B 中调用构造器 A 中的初始化代码,又不会重新创建一个 Java 对象,可以使用 this 关键字来调用相应的构造器。下面代码实现了在一个构造器中,直接使用另一个构造器的初始化代码。

    /** * @author Administrator */ public class ConstructorInvoke { public String name; public int count; public double weight; /** * 无参构造 */ public ConstructorInvoke() { } /** * 两个参数的构造器 * * @param name 名称 * @param count 数量 */ public ConstructorInvoke(String name, int count) { this.name = name; this.count = count; } /** * 三个参数的构造器 * * @param name 名称 * @param count 数量 * @param weight 重量 */ public ConstructorInvoke(String name, int count, double weight) { /*this.name = name; this.count = count;*/ // 通过 this 调用另一个重载的构造器的初始化代码 this(name, count); // 下面 this 引用该构造器正在初始化的 Java 对象 this.weight = weight; } public static void main(String[] args) { ConstructorInvoke radish = new ConstructorInvoke("萝卜", 200, 2); System.out.println("名称:" + radish.name + "\t数量:" + radish.count + "\t" + "重量" + radish.weight); } }

    2.2、运行结果

    名称:萝卜 数量:200 重量2.0

    ​ 上面的 ConstructorInvoke 类里包含了三个构造器,其中第三个构造器通过 this 来调用另一个重载构造器的初始化代码。程序中 this (name, color ); 调用表明调用该类另一个带两个字符串参数的构造器。

    ​ 使用 this 调用另一个重载的构造器,只能在构造器中使用,而且必须作为构造器执行体的第一条语句 ,使用 this调用重载的构造器时,系统会根据this 后括号里的实参来调用形参列表与之对应的构造器。

    3、知识补充

    3.1、为什么要用 this 来调用构造器,而不是直接复制代码?

    ​ 从图1中其实就可以知道为什么要调用构造器,而不是复制代码了。为啥?😉 往下看 baby

    ​ 因为软件是一个需要不断更新的产品,如果有一天需要更新图1中构造器 A 的初始化代码,假设构造器 B、构造器 C 都含有相同的初始化代码,则需要同时打开构造器 A、构造器 B、构造器 C …… 的代码进行修改;反之,如果构造器 B、构造器 C …… 是通过 this 调用了构造器 A 的初始化代码,则只需要打开构造器 A 进行修改既可。

    如果仅仅从软件功能实现上来看:这样复制、粘贴确实可以实现所想要的功能;从软件工程的角度来看:这样做是相当糟糕的。

    ​ 在软件开发里有一个规则:不要把相同的代码段书写两次以上(就是冗余代码,现在有印象了吧(∩_∩))。因此,尽量避免相同的代码重复出现,充分复用每一段代码(毕竟按代码行数算钱的时代已经过去 ( ̄▽ ̄)),既可让程序代码更加简洁,也可以降低软件的维护成本。

    Processed: 0.011, SQL: 9