方法是用来完成某个任务的,在 C 语言里我们通常叫做函数,单独写出函数是为了更加方便,也为了更清晰地看到代码的作用。
一、Java 里的方法
1.方法的格式示例:
修饰符 返回值类型 方法名(参数类型 参数名, ...) { 方法体; return 返回值; }这段内容其实并不复杂,只要记住格式即可。需要特别注意的是,返回值的类型不能写错。通常在 main 方法中调用某个方法时,要留意该方法的返回值类型;如果没有返回值,则使用 void。最后,在调用方法时,还要判断是否需要接收其返回值。
2.方法里的实参和形参
简单来说,实参是指在调用方法时实际传入的参数,而形参是方法定义时用来接收这些参数的变量。需要注意的是,实参和形参分别存储在不同的栈帧中,调用方法时会为形参分配新的内存空间,所以方法里修改形参并不会影响实参。
下面通过一个示例来理解实参和形参的区别:
public class ParamDemo { // 形参:方法定义时用来接收参数的变量 public static void change(int num) { num = 100; // 修改形参的值 System.out.println("方法内修改后的 num = " + num); } public static void main(String[] args) { int num = 10; // 实参:调用方法时实际传入的参数 System.out.println("调用前 num = " + num); change(num); // 把实参 num 的值传给形参 System.out.println("调用后 num = " + num); // 实参不受影响,仍为 10 } }运行结果:
调用前 num = 10 方法内修改后的 num = 100 调用后 num = 10从结果可以看出,方法内修改形参 num 并不会影响 main 方法中的实参 num,因为两者存储在不同的栈帧中,形参只是实参值的一份拷贝。
二、重载
重载简单来说,就是允许同一个方法名被重复使用,但为了区分不同的功能,方法所接收的形参在个数、顺序或类型上必须有所不同。
下面通过一个示例来理解重载:
public class OverloadDemo { // 两个整数相加 public static int add(int a, int b) { return a + b; } // 三个整数相加(参数个数不同) public static int add(int a, int b, int c) { return a + b + c; } // 两个小数相加(参数类型不同) public static double add(double a, double b) { return a + b; } public static void main(String[] args) { System.out.println(add(1, 2)); // 调用 int add(int, int) System.out.println(add(1, 2, 3)); // 调用 int add(int, int, int) System.out.println(add(1.5, 2.5)); // 调用 double add(double, double) } }所以重载解决了重复定义方法名的问题,让同一个方法名可以处理不同类型或数量的参数,提高了代码的复用性和可读性。
上面的三个 add 方法名称相同,但参数个数或类型不同,这就是重载。调用时,Java 会根据传入实参的个数和类型,自动匹配对应的方法。
三、递归
递归需要一定的数学基础来理解。递归包含两个动作:一个是「递」,即不断向更小的问题推进;一个是「归」,即逐层返回结果。理解递归时,可以抓住两个关键点:第一,找到递归的结束条件(递的终点);第二,找到递归的推导公式(递推关系)。思考时要纵向展开,先想清楚整体逻辑,不要一开始就陷入代码细节。
下面通过一个计算阶乘的示例来理解递归:
public class FactorialDemo { // 递归方法:计算 n 的阶乘 public static int factorial(int n) { // 递归结束条件:n 为 0 或 1 时,直接返回 1 if (n == 0 || n == 1) { return 1; } // 递推公式:n! = n * (n-1)! return n * factorial(n - 1); } public static void main(String[] args) { System.out.println("5! = " + factorial(5)); System.out.println("6! = " + factorial(6)); } }运行结果:
5! = 120 6! = 720以 factorial(5) 为例,递归的执行过程如下:
factorial(5) = 5 * factorial(4) = 5 * 4 * factorial(3) = 5 * 4 * 3 * factorial(2) = 5 * 4 * 3 * 2 * factorial(1) = 5 * 4 * 3 * 2 * 1 = 120可以看到,递归先不断「递」到结束条件 factorial(1),再逐层「归」回并计算结果。只要找到结束条件和递推公式,递归的代码往往非常简洁。
下面出两道递归练习题,先自己动手写一写,再对照思路检查:
练习一:斐波那契数列
斐波那契数列的定义是:第 1 项和第 2 项都是 1,从第 3 项开始,每一项都等于前两项之和,即 1、1、2、3、5、8、13……请用递归方法实现一个函数,输入一个正整数 n,返回第 n 项的值。
提示:先想清楚递归的结束条件是什么,再写出递推公式。
练习二:数字各位之和
给定一个非负整数,请用递归方法计算它各位数字之和。例如输入 1234,应返回 1 + 2 + 3 + 4 = 10;输入 7,应返回 7。
提示:想一想如何通过取余和整除,把一个大问题逐步拆成更小的问题。