目录
1.方法的基本用法
1.1.什么是方法
1.2.方法定义语法
1.3.方法调用的执行过程
1.4.实参和形参的关系
1.5.方法的返回值
2.方法重载
2.1.方法重载定义
2.2.代码示例
3.方法递归
3.1.方法递归定义
3.2.方法递归使用条件
3.3.递归与非递归优劣比较
3.4.递归执行过程分析
1.方法的基本用法
1.1.什么是方法
方法就是一个代码片段。类似于C语言中的函数。分为主方法和自己定义的方法。
方法存在的意义:
- 能够模块化地组织代码(当代码规模比较复杂时)。
- 实现代码复用。直接调用现有写好的方法,不必重复造轮子。
- 让代码更好理解,更简单。
1.2.方法定义语法
//方法定义
public static 方法返回值 方法名称([参数类型 形参 ...]){
方法体代码;
[return [返回值];] //没有返回值直接return;表示方法直接退出
}
//方法调用
返回值变量 = 方法名称(实参...);
注:
1).public 和 static 两个关键字在此处具有特定含义。(后面文章有详细介绍)。
2).方法定义时,参数可有可无。若有要指定其类型。
3).方法定义时,返回值可有可无。若无返回值,则返回值类型应写成 void。
4).方法定义时的参数称为 "形参",方法调用时的参数称为 "实参"。
5).方法的定义必须在类之中,方法定义写在方法调用位置的上方或者下方均可。
6).Java 中没有 "函数声明" 的概念。定义一个方法,要有方法体实现{ }。(特殊方法除外,抽象方法等)
1.3.方法调用的执行过程
- 定义方法时,不会执行方法的代码。只有调用方法时才会执行。
- 当方法被调用时,会将实参赋值给形参。
- 参数传递完毕后,就会执行到方法体代码。
- 当方法执行完毕之后(遇到 return 语句),回到方法调用位置继续往下执行。
- 一个方法可以被多次调用。
(对方法的注释采用文档注释)
1.4.实参和形参的关系
形参:方法定义时的参数;实参:方法调用时的参数。
代码示例:交换两个整型变量
class Test {
public static void main(String[] args) {
int a = 10;
int b = 20;
swap(a, b);
System.out.println("a = " + a + " b = " + b);
}
public static void swap(int x, int y) {
int tmp = x;
x = y;
y = tmp;
}
}
// 运行结果
a = 10 b = 20
原因分析:
int a = 10;
int b = 20;
int x = a;
int y = b;
int tmp = x;
x = y;
y = tmp;
Java中的参数传递只有值传递!对于基本类型来说,形参相当于实参的拷贝。即传值调用。对 x 和 y 的修改,不影响 a 和 b。即形参交换了,实参并没有交换。
解决办法:传引用类型参数(例如数组),它还是值传递,只不过这里的值是“地址”。
class Test {
public static void main(String[] args) {
int[] arr = {10, 20};
swap(arr);
System.out.println("a = " + arr[0] + " b = " + arr[1]);
}
public static void swap(int[] arr) {
int tmp = arr[0];
arr[0] = arr[1];
arr[1] = tmp;
}
}
// 运行结果
a = 20 b = 10
1.5.方法的返回值
方法的返回值是可有可无的。根据当前方法的作用来判断是否有返回值。
有返回值:return 返回值;
无返回值(方法返回值定义为void):不写return语句;也可写只写return语句,直接退出方法。
2.方法重载
2.1.方法重载定义
在同一个类中,定义了一组(若干个)方法,其方法的名称相同,方法的参数不同(参数个数或参数类型),与方法返回值类型和修饰符无关。
2.2.代码示例
class Test {
public static void main(String[] args) {
int a = 10;
int b = 20;
int ret = add(a, b);
System.out.println("ret = " + ret);
double a2 = 10.5;
double b2 = 20.5;
double ret2 = add(a2, b2);
System.out.println("ret2 = " + ret2);
double a3 = 10.5;
double b3 = 10.5;
double c3 = 20.5;
double ret3 = add(a3, b3, c3);
System.out.println("ret3 = " + ret3);
}
public static int add(int x, int y) {
return x + y;
}
public static double add(int x, int y) {
return x + y;
}//编译会报错
//参数类型为int,返回值类型为double,int->double是小类型->大类型,可自动转换类型。
//与上面的方法只是返回值不同,当两个方法名相同, 参数相同, 但返回值不同时, 不构成重载。
public static double add(double x, double y) {
return x + y;
}
public static double add(double x, double y, double z) {
return x + y + z;
}
}
println()就是一个最常用的重载方法。
3.方法递归
3.1.方法递归定义
一个方法在执行过程中调用自身,称为递归。一定要注意方法的语义(方法写出来的作用)。
- 递:拆解问题
- 归:碰到终止条件时,陆续给返回值
3.2.方法递归使用条件
- 一个大问题可以拆分为多个子问题
- 拆分后的子问题和原问题,除了数据规模不一样,解决思路完全相同
- 必须存在递归终止条件
3.3.递归与非递归优劣比较
递归:程序执行速度慢,原因是进行了大量的重复计算,但代码好想,好写;
非递归(迭代,循环):程序执行效率更高。
3.4.递归执行过程分析
要想理解清楚递归执行过程,必须先理解清楚 "方法的执行过程",尤其是 "方法执行结束之后,回到调用位置继续往下执行。
代码示例: 递归求 N 的阶乘
public static void main(String[] args) {
int n = 5;
int ret = factor(n);
System.out.println("ret = " + ret);
}
public static int factor(int n) {
System.out.println("函数开始, n = " + n);
if (n == 1) {
System.out.println("函数结束, n = 1 ret = 1");
return 1;
}
int ret = n * factor(n - 1);
System.out.println("函数结束, n = " + n + " ret = " + ret);
return ret;
}
// 执行结果
函数开始, n = 5
函数开始, n = 4
函数开始, n = 3
函数开始, n = 2
函数开始, n = 1
函数结束, n = 1 ret = 1
函数结束, n = 2 ret = 2
函数结束, n = 3 ret = 6
函数结束, n = 4 ret = 24
函数结束, n = 5 ret = 120
ret = 120
程序按照序号中标识的 (1) -> (8) 的顺序执行。(1)-(4)递;(5)-(8)归。
方法调用的时候,会有一个"栈" 这样的内存空间描述当前的调用关系。称为调用栈。
每一次的方法调用就称为一个"栈帧",每个栈帧中包含了这次调用的参数是哪些,返回到哪里继续执行等信息。