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

核心概念
“类内函数调用函数调用函数”描述的是一个对象的方法调用另一个方法,而这个被调用的方法又可能再调用第三个方法,以此类推,这本质上就是在一个类的内部,方法之间的相互调用。
这种调用方式主要有两种形式:
- 实例方法调用实例方法:这是最常见的形式,一个对象的方法去调用同一个对象的另一个方法。
- 静态方法调用静态方法:一个
static方法去调用另一个static方法。
实例方法调用实例方法 (最常见)
当一个方法需要执行一个已经被该类中另一个方法定义好的逻辑时,我们就可以让一个方法去调用另一个方法,这样做的好处是 代码复用 和 逻辑清晰。
示例:一个 Car 类
假设我们有一个 Car 类,它有启动、行驶和停止的功能,我们可以这样设计:

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()
}
}
代码解析
-
drive()方法调用了startEngine()方法:- 当我们调用
myCar.drive()时,程序首先进入drive()方法。 - 在
drive()方法内部,this.startEngine();这行代码告诉程序:“调用当前这个myCar对象的startEngine()方法”。 this关键字就代表“当前这个对象实例”,在实例方法中,this可以被省略,startEngine();和this.startEngine();是完全一样的。- 执行完
startEngine()后,程序会返回到drive()方法中,继续执行下一行代码。
- 当我们调用
-
stop()方法调用了stopEngine()方法:- 原理同上,
myCar.stop()的执行过程中,会去调用myCar.stopEngine()。
- 原理同上,
优点
- 代码复用:
startEngine的逻辑只写了一次,但可以在drive和其他任何需要启动引擎的地方被调用。 - 封装性:
drive方法封装了“准备行驶 -> 启动引擎 -> 开始行驶”这一系列完整操作,使用者只需要调用drive(),而不需要关心背后需要启动引擎这个细节。 - 逻辑清晰:每个方法只负责一个小的、单一的功能,组合起来完成一个复杂任务,代码结构更清晰。
静态方法调用静态方法
静态方法属于类本身,而不是类的某个实例,静态方法之间可以直接通过类名进行调用,或者直接调用(如果在同一个类中)。
示例:一个 MathUtils 工具类
工具类通常包含一些与特定对象无关的通用方法,因此它们的方法大多是 static 的。

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);
}
}
代码解析
pow4()方法调用了两次square()方法:- 因为
pow4和square都是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"):
new StringBuilder():创建了一个StringBuilder对象,我们称之为obj1。obj1.append("A"):- 调用
obj1的append方法。 append方法内部将 "A" 添加到obj1中。append方法执行完毕,返回obj1本身。
- 调用
.append("B"):- 因为上一步返回的是
obj1,所以这行代码等价于obj1.append("B")。 - 再次调用
obj1的append方法。 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,如 StringBuilder、Stream。 |
理解这三种调用方式是掌握 Java 面向对象编程的关键一步,它能让你的代码更加模块化、可读性更强,也更易于维护。
