杰瑞科技汇

java 类内函数调用函数调用函数

这其实是一个非常基础且核心的 Java 编程思想,通常我们称之为 方法链链式调用

java 类内函数调用函数调用函数-图1
(图片来源网络,侵删)

核心概念

“类内函数调用函数调用函数”描述的是一个对象的方法调用另一个方法,而这个被调用的方法又可能再调用第三个方法,以此类推,这本质上就是在一个类的内部,方法之间的相互调用。

这种调用方式主要有两种形式:

  1. 实例方法调用实例方法:这是最常见的形式,一个对象的方法去调用同一个对象的另一个方法。
  2. 静态方法调用静态方法:一个 static 方法去调用另一个 static 方法。

实例方法调用实例方法 (最常见)

当一个方法需要执行一个已经被该类中另一个方法定义好的逻辑时,我们就可以让一个方法去调用另一个方法,这样做的好处是 代码复用逻辑清晰

示例:一个 Car

假设我们有一个 Car 类,它有启动、行驶和停止的功能,我们可以这样设计:

java 类内函数调用函数调用函数-图2
(图片来源网络,侵删)
public class Car {
    private String brand; // 品牌
    private boolean isEngineOn; // 引擎是否启动
    public Car(String brand) {
        this.brand = brand;
        this.isEngineOn = false;
        System.out.println("一辆 " + brand + " 汽车被创建出来了。");
    }
    // 方法一:启动引擎
    public void startEngine() {
        if (!isEngineOn) {
            isEngineOn = true;
            System.out.println("引擎启动成功!");
        } else {
            System.out.println("引擎已经在运行了。");
        }
    }
    // 方法二:行驶汽车
    // 在行驶之前,需要确保引擎已经启动,所以它会调用 startEngine()
    public void drive() {
        System.out.println("准备开始行驶...");
        // 关键点:这里调用了同一个对象的 startEngine() 方法
        this.startEngine(); // "this" 关键字可以省略,通常我们都会省略
        System.out.println("汽车 " + brand + " 正在行驶中...");
    }
    // 方法三:停止汽车
    // 停止行驶后,我们可能还想熄火,所以它会调用 stopEngine()
    public void stop() {
        System.out.println("准备停车...");
        // 关键点:这里调用了同一个对象的 stopEngine() 方法
        this.stopEngine();
        System.out.println("汽车 " + brand + " 已安全停稳。");
    }
    // 方法四:熄火引擎
    public void stopEngine() {
        if (isEngineOn) {
            isEngineOn = false;
            System.out.println("引擎已熄火。");
        } else {
            System.out.println("引擎本来就是熄火状态。");
        }
    }
    public static void main(String[] args) {
        Car myCar = new Car("特斯拉 Model 3");
        // 场景一:直接调用
        System.out.println("--- 场景一:直接调用 ---");
        myCar.startEngine(); // 启动引擎
        myCar.stopEngine();  // 熄火引擎
        System.out.println("\n--- 场景二:函数调用函数 ---");
        // 场景二:函数调用函数
        // 我们想“行驶”,但 `drive` 方法内部会自动处理“启动引擎”的逻辑
        myCar.drive(); // 1. 调用 myCar.drive()
                       // 2. 在 drive() 内部,调用了 myCar.startEngine()
                       // 3. 然后继续执行 drive() 的其余代码
        System.out.println("\n--- 场景三:停车 ---");
        // 我们想“停车”,但 `stop` 方法内部会自动处理“熄火”的逻辑
        myCar.stop(); // 1. 调用 myCar.stop()
                      // 2. 在 stop() 内部,调用了 myCar.stopEngine()
    }
}

代码解析

  1. drive() 方法调用了 startEngine() 方法

    • 当我们调用 myCar.drive() 时,程序首先进入 drive() 方法。
    • drive() 方法内部,this.startEngine(); 这行代码告诉程序:“调用当前这个 myCar 对象的 startEngine() 方法”。
    • this 关键字就代表“当前这个对象实例”,在实例方法中,this 可以被省略,startEngine();this.startEngine(); 是完全一样的。
    • 执行完 startEngine() 后,程序会返回到 drive() 方法中,继续执行下一行代码。
  2. stop() 方法调用了 stopEngine() 方法

    • 原理同上,myCar.stop() 的执行过程中,会去调用 myCar.stopEngine()

优点

  • 代码复用startEngine 的逻辑只写了一次,但可以在 drive 和其他任何需要启动引擎的地方被调用。
  • 封装性drive 方法封装了“准备行驶 -> 启动引擎 -> 开始行驶”这一系列完整操作,使用者只需要调用 drive(),而不需要关心背后需要启动引擎这个细节。
  • 逻辑清晰:每个方法只负责一个小的、单一的功能,组合起来完成一个复杂任务,代码结构更清晰。

静态方法调用静态方法

静态方法属于类本身,而不是类的某个实例,静态方法之间可以直接通过类名进行调用,或者直接调用(如果在同一个类中)。

示例:一个 MathUtils 工具类

工具类通常包含一些与特定对象无关的通用方法,因此它们的方法大多是 static 的。

java 类内函数调用函数调用函数-图3
(图片来源网络,侵删)
public class MathUtils {
    // 私有构造函数,防止被实例化,因为这是一个工具类
    private MathUtils() {}
    // 静态方法:计算平方
    public static double square(double number) {
        return number * number;
    }
    // 静态方法:计算立方
    public static double cube(double number) {
        return number * number * number;
    }
    // 静态方法:计算四次方
    // 它需要用到平方的计算逻辑,所以它调用了 square() 方法
    public static double pow4(double number) {
        System.out.println("准备计算 " + number + " 的四次方...");
        // 关键点:在同一个类中,静态方法可以直接调用其他静态方法
        double squared = square(number); // 调用同一个类的静态方法
        System.out.println("先计算得到平方: " + squared);
        // 然后再次调用 square 方法来得到四次方
        double result = square(squared);
        return result;
    }
    public static void main(String[] args) {
        double num = 3.0;
        // 直接调用静态方法
        double sq = MathUtils.square(num);
        System.out.println(num + " 的平方是: " + sq);
        System.out.println("\n--- 静态方法调用静态方法 ---");
        // 调用 pow4,它内部会调用两次 square
        double p4 = MathUtils.pow4(num);
        System.out.println(num + " 的四次方是: " + p4);
    }
}

代码解析

  1. pow4() 方法调用了两次 square() 方法
    • 因为 pow4square 都是 static 方法,并且属于同一个类 MathUtils
    • pow4 内部,我们可以直接通过方法名 square(number) 来调用它,这等同于 MathUtils.square(number),但在同一个类中,我们通常省略类名。
    • 这种调用方式清晰地展示了 pow4 的实现依赖于 square 的功能。

链式调用 (Chaining Method Calls)

这是一种更高级、更优雅的“函数调用函数”的形式,常见于 构建器模式流式 API (如 Java Stream),它的特点是 被调用的方法会返回调用它的对象本身 (this)

示例:一个 StringBuilder 的经典例子

StringBuilder 是链式调用的典型代表。

public class StringBuilderExample {
    public static void main(String[] args) {
        // 不使用链式调用
        StringBuilder sb1 = new StringBuilder();
        sb1.append("Hello");
        sb1.append(" ");
        sb1.append("World");
        sb1.append("!");
        String result1 = sb1.toString();
        System.out.println(result1); // 输出: Hello World!
        System.out.println("--------------------");
        // 使用链式调用
        // append() 方法在执行完后,会返回 StringBuilder 对象本身
        String result2 = new StringBuilder()
                .append("Hello")
                .append(" ")
                .append("World")
                .append("!")
                .toString();
        System.out.println(result2); // 输出: Hello World!
    }
}

为什么链式调用能工作?

我们来看 StringBuilder 内部 append 方法的简化版:

public class StringBuilder {
    // ... 内部实现 ...
    // 简化的 append 方法
    public StringBuilder append(String str) {
        // ... 实现将 str 添加到内部的字符序列中的逻辑 ...
        // 关键点:执行完添加逻辑后,返回当前对象
        return this; // "this" 指的就是调用这个 append 方法的 StringBuilder 对象
    }
    public String toString() {
        // ... 将字符序列转换为字符串的逻辑 ...
        return "the final string";
    }
}

执行流程分析 new StringBuilder().append("A").append("B"):

  1. new StringBuilder():创建了一个 StringBuilder 对象,我们称之为 obj1
  2. obj1.append("A")
    • 调用 obj1append 方法。
    • append 方法内部将 "A" 添加到 obj1 中。
    • append 方法执行完毕,返回 obj1 本身
  3. .append("B")
    • 因为上一步返回的是 obj1,所以这行代码等价于 obj1.append("B")
    • 再次调用 obj1append 方法。
    • append 方法内部将 "B" 添加到 obj1 中。
    • append 方法执行完毕,再次返回 obj1 本身。

整个表达式返回的就是那个被修改过的 obj1

类型 调用方式 关键点 常见场景
实例方法调用实例方法 methodA() { this.methodB(); } this 代表当前对象,可以省略。 对象行为组合,如 car.drive() 内部调用 car.startEngine()
静态方法调用静态方法 staticMethodA() { MyClass.staticMethodB(); } 直接通过类名或方法名调用(同类中)。 工具类,如 MathUtils.pow4() 内部调用 MathUtils.square()
链式调用 methodA() { ...; return this; } 被调用的方法必须返回调用者对象本身 (this) 构建器模式、流式 API,如 StringBuilderStream

理解这三种调用方式是掌握 Java 面向对象编程的关键一步,它能让你的代码更加模块化、可读性更强,也更易于维护。

分享:
扫描分享到社交APP
上一篇
下一篇