核心概念:方法与方法调用
在 Java 中,我们通常不使用“函数”这个词,而是用“方法”(Method),方法是包含在类中的一段可重用的代码块,用于执行特定的任务。

- 方法定义:创建一个方法,指定其名称、参数、返回值类型和方法体。
- 方法调用:在程序的其他地方,使用方法名并传入所需的参数来执行该方法。
基础实现:方法调用方法
这是最直接的理解,一个方法 A 的代码块中,调用了另一个方法 B。
示例:一个简单的调用链
我们创建一个 Calculator 类,它有一个 add 方法,然后在一个 performCalculation 方法中调用 add。
// Calculator.java
public class Calculator {
/**
* 这是一个被调用的方法,用于执行加法运算。
* @param a 第一个加数
* @param b 第二个加数
* @return 两个数的和
*/
public int add(int a, int b) {
System.out.println("正在调用 add 方法...");
int sum = a + b;
System.out.println("add 方法计算完成,结果为: " + sum);
return sum;
}
/**
* 这是调用其他方法的方法。
* 它会调用 add 方法,并打印最终结果。
*/
public void performCalculation() {
System.out.println("performCalculation 方法开始执行。");
// performCalculation 方法调用了 add 方法
int result = add(10, 5); // <--- 关键的调用步骤
System.out.println("performCalculation 方法继续执行,获得 add 的结果: " + result);
System.out.println("performCalculation 方法执行结束。");
}
// 主方法,程序的入口点
public static void main(String[] args) {
// 创建 Calculator 类的实例
Calculator myCalculator = new Calculator();
// 调用 performCalculation 方法
myCalculator.performCalculation();
}
}
执行流程分析:
main方法启动,创建Calculator对象myCalculator。main方法调用myCalculator.performCalculation()。- 程序流进入
performCalculation方法,打印第一行信息。 performCalculation方法执行到int result = add(10, 5);。- 程序流跳转到
add方法,将10和5分别传递给参数a和b。 add方法执行计算,打印信息,并返回15。- 程序流返回到
performCalculation方法中调用add的地方,将返回值15赋给变量result。 performCalculation方法继续执行,打印最终信息,然后结束。- 程序流返回
main方法,整个程序结束。
输出结果:

performCalculation 方法开始执行。
正在调用 add 方法...
add 方法计算完成,结果为: 15
performCalculation 方法继续执行,获得 add 的结果: 15
performCalculation 方法执行结束。
进阶实现:调用链(方法调用方法调用方法...)
我们可以将上面的模式扩展得更长,方法 A 调用方法 B,方法 B 再调用方法 C。
示例:处理用户输入的流程
想象一个处理用户登录的流程:
handleUserLogin()(处理登录) -> 调用validateCredentials()(验证凭据) -> 调用checkDatabaseForUser()(检查数据库)
// LoginService.java
public class LoginService {
public void handleUserLogin(String username, String password) {
System.out.println("handleUserLogin: 开始处理用户登录请求...");
// 调用第二个方法
boolean isValid = validateCredentials(username, password);
if (isValid) {
System.out.println("handleUserLogin: 登录成功!");
} else {
System.out.println("handleUserLogin: 登录失败,用户名或密码错误。");
}
System.out.println("handleUserLogin: 登录处理结束。");
}
private boolean validateCredentials(String username, String password) {
System.out.println("validateCredentials: 开始验证用户凭据...");
// 调用第三个方法
boolean userExists = checkDatabaseForUser(username, password);
if (userExists) {
System.out.println("validateCredentials: 凭据验证通过。");
return true;
} else {
System.out.println("validateCredentials: 凭据验证失败。");
return false;
}
}
// 模拟一个数据库查询方法
private boolean checkDatabaseForUser(String username, String password) {
System.out.println("checkDatabaseForUser: 正在模拟查询数据库...");
// 在真实场景中,这里会连接数据库进行查询
// 为了演示,我们假设用户名是 "admin",密码是 "123456"
boolean found = "admin".equals(username) && "123456".equals(password);
System.out.println("checkDatabaseForUser: 数据库查询完成。");
return found;
}
public static void main(String[] args) {
LoginService service = new LoginService();
System.out.println("--- 测试成功登录 ---");
service.handleUserLogin("admin", "123456");
System.out.println("\n--- 测试失败登录 ---");
service.handleUserLogin("wrongUser", "wrongPass");
}
}
执行流程分析(成功登录时):
main调用handleUserLogin("admin", "123456")。handleUserLogin调用validateCredentials("admin", "123456")。validateCredentials调用checkDatabaseForUser("admin", "123456")。checkDatabaseForUser执行其逻辑并返回true。- 程序流返回到
validateCredentials,userExists变量为true,validateCredentials返回true。 - 程序流返回到
handleUserLogin,isValid变量为true,执行成功分支。
输出结果:

--- 测试成功登录 ---
handleUserLogin: 开始处理用户登录请求...
validateCredentials: 开始验证用户凭据...
checkDatabaseForUser: 正在模拟查询数据库...
checkDatabaseForUser: 数据库查询完成。
validateCredentials: 凭据验证通过。
handleUserLogin: 登录成功!
handleUserLogin: 登录处理结束。
--- 测试失败登录 ---
handleUserLogin: 开始处理用户登录请求...
validateCredentials: 开始验证用户凭据...
checkDatabaseForUser: 正在模拟查询数据库...
checkDatabaseForUser: 数据库查询完成。
validateCredentials: 凭据验证失败。
handleUserLogin: 登录失败,用户名或密码错误。
handleUserLogin: 登录处理结束。
重要的注意事项
A. 参数传递
Java 中,参数传递分为两种:
-
值传递:对于基本数据类型(
int,double,char等),传递的是值的副本,在方法内部修改这个副本,不会影响原始变量。public void changeValue(int x) { x = 100; // 只修改了副本 } // main方法中调用 changeValue(myInt) 后,myInt 的值不变 -
引用传递:对于对象(
String,Calculator等),传递的是对象内存地址的副本,通过这个地址副本,你仍然可以操作对象本身的成员变量,但你不能改变原始的引用(让它指向另一个新对象)。public void changeObjectState(MyObject obj) { obj.setField(50); // 可以修改对象内部的状态 // obj = new MyObject(); // 这不会改变 main 方法中的原始引用 }
B. 返回值
被调用的方法可以通过 return 语句将一个值返回给它的调用者,调用者必须:
- 使用一个变量来接收返回值(如果返回值类型不是
void)。 - 处理返回的值。
// 调用并接收返回值 int sum = myCalculator.add(5, 3); // 也可以直接将返回值用于其他表达式 int total = myCalculator.add(5, 3) * 2; // total 会是 16
C. 递归:方法调用自身
一种特殊但非常强大的“方法调用方法”是递归,即方法直接或间接地调用自身。
示例:计算阶乘
public class Factorial {
public static long factorial(int n) {
// 基本情况(递归的出口)
if (n <= 1) {
return 1;
}
// 递归步骤
else {
return n * factorial(n - 1); // factorial 调用了自己
}
}
public static void main(String[] args) {
int number = 5;
long result = factorial(number);
System.out.println(number + " 的阶乘是: " + result); // 输出 120
}
}
调用链(factorial(5)):
factorial(5) -> 5 * factorial(4)
factorial(4) -> 4 * factorial(3)
factorial(3) -> 3 * factorial(2)
factorial(2) -> 2 * factorial(1)
factorial(1) -> 1 (到达基本情况,开始返回)
然后结果层层返回,最终计算出 120。
实现“函数调用方法调用方法”是结构化编程和面向对象编程的基石,关键在于:
- 定义清晰的方法:每个方法只做一件事,并拥有明确的输入(参数)和输出(返回值)。
- 构建调用链:在一个方法中,根据业务逻辑调用其他方法,形成层次分明的结构。
- 理解执行流程:明白程序是如何在不同方法之间跳转和返回的,这对于调试和理解代码至关重要。
- 注意参数和返回值:正确地传递数据和接收结果,避免因误解传递机制而导致的 bug。
掌握这种方法调用模式,是编写出结构清晰、可维护、可扩展的 Java 代码的第一步。
