目录
本章我们主要讲解:
简单来说方法:方法就是一个代码片段,类似于 C 语言中的函数
// 方法定义
public static 方法返回值 方法名称([参数类型 形参 ...]){
方法体代码;
[return 返回值];
}
// 方法调用
返回值变量 = 方法名称(实参...);
class Test {
public static void main(String[] args) {
int a = 10;
int b = 20;
// 方法的调用
int ret = add(a, b);
System.out.println("ret = " + ret);
}
// 方法的定义
public static int add(int x, int y) {
return x + y;
}
}
// 执行结果
ret = 30
同样的与C语言一样的是:当方法被调用时,会将实参赋值给形参(一份临时拷贝)
public 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 a, int b){
int tmp = a;
int a = b;
int b = tmp;
}
}
// 运行结果为 a = 10 b = 20
注:swap 方法里只将形参的值互换了,但是实参的值没有互换
在 Java 中想做到修改实参的值我们需要用到引用类型(引用可以理解为"地址")
public 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
定义:同一个方法名字相同,提供不同类型的实现,称为重载
规则:
public class Test{
public static void main(String[] args){
int a1 = 10;
int b1 = 20;
int ret1 = add(a1, b1);
System.out.println("ret1 = " + ret1);
double a2 = 1.5;
double b2 = 2.4;
double ret2 = a2 + b2;
System.ouy.println("ret2 =" + ret2);
}
public static int addInt(int a, int b){
return a + b;
}
public static double addDouble(double a, double b){
return a + b;
}
}
对于求不同类型的数据和,在上面我们写了addInt和addDouble两个方法,但是 Java 认为 addInt 这样的名字不友好,不如直接就叫 add,由此重载便派上用场了
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(double x, double y) {
return x + y;
}
public static double add(double x, double y, double z) {
return x + y + z;
}
}
定义:一个方法在执行过程中调用自身,就称为“递归”
简单来看递归即是"递推和回归":满足条件时进行递推调用方法,不满足时开始回归 对于没有限制条件的方法调用,则会出现栈溢出(方法的调用会开辟空间,而内存是有限的)
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
public static void print(int num) {
if (num > 9) {
print(num / 10);
}
System.out.println(num % 10);
}
public static int sum(int num) {
if (num == 1) {
return 1;
}
return num + sum(num - 1);
}
public static int sum(int num) {
if (num < 10) {
return num;
}
return num % 10 + sum(num / 10);
}
public static int fib(int n) {
if (n == 1 || n == 2) {
return 1;
}
return fib(n - 1) + fib(n - 2);
}
当我们求数字较大的项时, 程序执行速度极慢(进行了大量的重复运算) 可以使用循环的方式来求斐波那契数列问题, 避免出现冗余运算
public static int fib(int n) {
int last2 = 1;
int last1 = 1;
int cur = 0;
for (int i = 3; i <= n; i++) {
cur = last1 + last2;
last2 = last1;
last1 = cur;
}
return cur;
}
什么时候使用:问题递归非递归都能写且没有多大的问题时,选择递归
1. 简洁 2.在树的前序,中序,后序遍历算法中,递归的实现明显要比循环简单得多
1.递归由于是函数调用自身,而函数调用是有时间和空间的消耗的:每一次函数调用,都需要在内存栈中分配空间以保存参数、返回地址以及临时变量,而往栈中压入数据和弹出数据都需要时间。->效率 2.递归中很多计算都是重复的,由于其本质是把一个问题分解成两个或者多个小问题,多个小问题存在相互重叠的部分,则存在重复计算,如fibonacci斐波那契数列的递归实现。->效率 3.调用栈可能会溢出,其实每一次函数调用会在内存栈中分配空间,而每个进程的栈的容量是有限的,当调用的层次太多时,就会超出栈的容量,从而导致栈溢出。->性能