四、第四章——方法的基础语法、方法的重载机制、方法的递归

1 方法的基础语法

1.1 方法的引入

/*
以下程序不使用“方法”,分析程序存在哪些缺点
* 以下的代码都是完成两个int类型数据的和,相同的代码写了三遍,代码没有得到重复使用。
* 应该在java语言当中有这样的一种机身:
- 某个功能代码只需要写一遍。
- 要使用这个功能,只需要给这个功能传递具体的数据
- 这个功能完成之后返回一个最终的结果。
这样代码就可以重复利用了,提高代码复用性。 【这就是“方法】

* 使用这个方法我们称为“调用/invoke”
*/

public class MethodTest01
{
public static void main(String[] args){
//需求1:请编写程序计算10和20的和,并将结果输出
int a = 10;
int b = 20;
int c = a + b;
System.out.println(a + " + " + b + " = " + c);

//需求2:请编写程序计算111和222的和,并将结果输出
int d = 111;
int e = 222;
int f = d + e;
System.out.println(d + " + " + e + " = " + f);

//需求3:请编写程序计算10和20的和,并将结果输出
int h = 10;
int j = 20;
int m = h + j;
System.out.println(h + " + " + j + " = " + m);

//以上的三个需求其实就是一个需求,这个需求是:计算两个int类型数据的和,功能相同,只不过每一次参与计算的具体数据不同。
}
}
/*
以下直接使用方法这种机制 【这个例子不讲方法的语法】,分析程序的优点
* 代码得到了重复的使用。

方法的本质是什么?
* 方法就是一段代码片段,并且这段代码片段可以完成某个特定的功能,并且可以重复的使用。

方法,对应的英语单词:Method
方法在c语言叫做函数/Function

方法定义在类体当中,在一个类当中可以定义多个方法,方法编写的顺序没有先后顺序,可以随意

方法体当中不能再定义方法

方法体由java语句构成,方法体当中的代码遵守自上而下的顺序依次执行。
*/

public class MethodTest02
{
public static void main(String[] args){
//计算两个int类型数据的和
MethodTest02.sumInt(10, 20);
MethodTest02.sumInt(234, 22);
MethodTest02.sumInt(444, 888);
}

//单独的定义一个方法
//该方法完成计算两个int类型数据的和,并且将结果输出

public static void sumInt(int a, int b){
int c = a + b;
System.out.println(a + " + " + b + " = " + c);
}
}

 

1.2 方法的语法结构

1、方法怎么定义,语法结构:
[修饰符列表] 返回值类型 方法名(形式参数列表){
方法体;
}


2、对以上的语法结构进行解释说明:
2.1、关于修饰符列表
* 要选项,不是必须的
* 目前统一写成:public static 【以后讲】
* 方法的修饰符列表当中有“static关键字”的话,怎么调用这个方法?
- 类名.方法名(实际参数列表);

2.2、返回值类型
* 什么是返回值?
一个方法是可以完成某个特定功能的,这个功能结束之后大多数都是需要返回最终的执行结果的,执行结果可能是一个具体存在的数据。而这个具体存在的数据就是返回值。
* 返回值类型?
返回值是一个具体存在的数据,数据都是有类型的,此处需要指定的是返回值的具体类型。
* 返回值类型都可以指定哪些类型呢?
java任意一种类型都可以,包括基本数据类型和所有引用数据类型。
* 也可能这个方法执行结束之后不返回任何数据,java中规定,当一个方法执行结束之后不返回任何数据的话,返回值类型位置必须编写:void关键字
* 返回值类型可以是:
byte,short,int,long,float,double,char,...
* 返回值类型若不是void,表示这个方法执行结束之后必须返回一个具体的数值。当方法执行结束的时候没有返回任何数据的话编译器报错。怎么返回值呢?代码怎么写呢?"return 值;",并且要求“值”的数据类型必须和“方法的返回值类型”一致。不然编译器报错。
* 返回值类型是void的时候,在方法体当中不能编写“return 值;”这样的语句。但是可以编写“return ;”这样的语句。
* 只要带有return关键字的语句执行,return语句所在的方法结束。

2.3、方法名:
* 只要是合法的标识符就行
* 方法名最好见名知意
* 方法名最好是动词
* 方法名首字母要求小写,后面每个单词首字母大写

2.4、形式参数列表:简称形参
* 形参是局部变量:int a; double b; float c; String s;...
* 形参的个数可以是:0~N个
* 多个形参之间用“逗号”隔开
* 形参中起决定性作用的是形参的数据类型,形参的名字就是局部变量的名字。
* 方法在调用的时候,实际给这个方法传递的真实数据被称为:实际参数,简称实参
* 实参列表和形参列表必须满足:
- 数量相同
- 类型对应相同
例如:
方法定义
public static int sum(int a, int b){

}
方法调用
sum("abc", "def");  编译器报错
sum(10, 20);

2.5、方法体必须由大括号括起来,方法体当中的代码有顺序,遵循自上而下的顺序依次执行。并且方法体由java语句构成,每一个java语句以";"结尾


3、方法怎么调用?
方法只定义不去调用时不会执行的。只有在调用的时候才会执行。
语法规则: 《方法的修饰符列表当中有static》
类名.方法名(实参列表); 这是一条java语句,表示调用某个类的某个方法,传递这样的实参。


//public表示公开的
//class表示定义类
//MethodTest03是一个类名
public class MethodTest03  //表示定义一个公开的类,起名MethodTest03,由于是公开的类,所以源文件名必须叫:MethodTest03.java
{
//类体
//类体中不能直接编写java语句,除声明变量之外
//方法出现在类体当中

//方法
//public表示公开的
//static表示静态的
//void表示方法执行的结束之后不返回任何数据
//main是方法名:主方法
//(String[] args):形式参数列表,其中String[]是一种引用数据类型,args是一个局部变量的变量名
//所以以下只有args这个局部变量的变量名是随意的
//主方法就需要这样固定编写,这是程序的入口。 【SUN规定的必须这样写】

public static void main(String[] args){
//这里的程序是一定会执行的
//main方法是JVm负责调用的,是一个入口位置
//从这里作为起点开始执行程序
//既然是这样,我们就可以在这里编写java语句来调用其它的方法
//调用MethodTest03的sum方法,传递两个实参
MethodTest03.sum(10, 20);  //实参列表 【实际上执行到这里main方法暂停了,进入sum方法执行,sum方法执行结束之后表示main方法的该行执行结束

//注意:方法体当中的代码是有顺序的,遵循自上而下的顺序依次执行

//一个方法可以被重复使用,重复调用
int a = 100;
MethodTest03.sum(a, 500);  //(a, 500)实参列表

//两次调用方法
int k = 90;
int f = 10;
MethodTest03.sum(k, f);  //(k, f)实参列表
}

//定义一个方法,不是程序的入口
//方法作用:计算两个int类型数据的和,不要求返回结果,但是要求将结果直接输出到控制台
//修饰符列表:public static
//返回值类型:void
//方法名:sum
//形式参数列表:(int x, int y)
//方法体:主要任务是求和之后输出计算结果
public static void sum(int i, int j){  //(int i, int j)形参列表
System.out.println(i + " + " + j + " = " + (i + j));
return ;
}

}

 

1.3 方法的调用

/*
方法的调用不一定在main方法当中,可以在其他方法当中。
只要是程序可以执行到的位置,都可以去调用其它方法
*/

public class MethodTest04
{
public static void sum(int a, int b){
System.out.println(a + " + " + b + " = " + (a + b));

//调用doSome方法
MethodTest04.doSome();
}

//主方法
public static void main(String[] args){
//调用sum方法
MethodTest04.sum(1, 3);
System.out.println("hello world");
}

public static void doSome(){
System.out.println("do some!");
}
}
//方法调用的时候实参和形参要求个数对应相同,数据类型对应相同。
//类型不同的时候要求能够进行相应的自动类型转换

public class MethodTest05
{
public static void main(String[] args){
//编译错误:参数数量不同
// MethodTest05.sum();

//编译错误:实参和形参类型不是对应相同的
// MethodTest05.sum(true, false);

//可以
MethodTest05.sum(10L, 20L);

//存在自动类型转换:int --> long
MethodTest05.sum(10, 20);

//编译错误:参数类型不是对应相同的
MethodTest05.sum(3.0, 20);

//可以
MethodTest05.sum((long)3.0, 20);

}

public static void sum(long a, long b){
System.out.println(a + " + " + b + " = " + (a + b));
}
}
/*
方法调用:
1、方法的修饰符列表当中有static关键字,完整的调用方式是:类名.方法名(实参列表);

2、但是,有有时候“类名."可以省略,什么情况下可以省略呢?"
m1(){
m2();
}
m1方法和m2方法在同一个类体当中的时候,"类名."可以不省略不写。

3、建议在一个java源文件中只定义一个class,比较清晰
*/

public class MethodTest06
{
public static void main(String[] args){

//调用方法
MethodTest06.m();

//对于方法的修饰符列表当中有static关键字的:“类名.”可以省略不写吗
m();

//调用其它类 【不是本类中的】 方法
A.doOther();

//省略“类名.”试试
//编译报错,“类名.”省略之后,默认从当前类中找“doOther”方法,在当前类中该方法不存在。
// doOther();
}

public static void m(){
System.out.println("m method execute");
//完整的方式
MethodTest06.m2();

//省略的方式
m2();

//不想调用当前本类当中的m2方法,这个时候就必须添加“类名.”了
A.m2();
}

public static void m2(){
System.out.println("m method execute");
}
}


class A
{
public static void doOther(){
System.out.println("A's doOther method invoke");
}

public static void m2(){
System.out.println("A's m2 method execute");
}
}
/*
分析以下程序的输出结果
main begin
m1 begin
m2 begin
m3 begin
m3 over
m2 over
m1 over
main over

对于当前的程序来说
* main方法最先被调用,main方法也是最后一个结束。
* 最后调用的方法是m3方法,该方法最先结束。

main方法结束之后,整个程序结束了 【这句话只适合当前所讲内容】

不用刻意去记忆:
只要记住方法中的代码是自上而下的顺序依次执行即可。
当前行的程序在没有结束的时候,下一行代码是无法执行的。

*/

public class MethodTest07
{
public static void main(String[] args){
System.out.println("main begin");
m1();
System.out.println("main over");
}

public static void m1(){
System.out.println("m1 begin");
m2();
System.out.println("m2 over");
}

public static void m2(){
System.out.println("m2 begin");
m3();
System.out.println("m2 over");
}

public static void m3(){
System.out.println("m3 begin");
System.out.println("m3 over");
}
}

 

1.4 方法的返回值

/*
方法的返回值类型不是void的时候
1、返回值类型不是void的时候:要求方法必须保证百分百的执行“return 值;”这样的语句来完成值的返回。
没有这个语句编译器会报错。

2、一个方法有返回值的时候,当我们调用这个方法的时候,方法返回了一个值
- 对于调用者来说,这个返回值可以选择接收,也可以选择不接收。
- 但是大部分情况下我瘊都是选择接收的
*/

public class MethodTest08
{
public static void main(String[] args){
//调用方法
divide(10, 3);  //这里没有接收这个方法的返回数据

//这里接收一下方法执行结束之后的返回值
//采用变量接收
//变量的数据类型需要和返回值的数据类型相同,或者可以自动类型转换
//boolean b = divide(10, 3); //编译报错,类型不兼容

//赋值运算符的右边先执行,将执行结果赋值给左边的变量
int i = divide(10, 3);
System.out.println(i);

long x = divide(10, 3);
System.out.println(x);

System.out.println(divide( 10 , 3));

}

/*
需求:
请定义并实现一个方法,该方法可以计算两个int类型数据的商,要求将最终的计算结果返回给调用者。
*/

//编译报错:缺少返回语句
/*
public static int divide(int a, int b){

}
*/

//编译错误:缺少返回值
/*
public static int divide(int a, int b){
return;
}
*/

//编译错误:方法定义的时候要求返回一个int类型,此时返回布尔类型,类型不兼容。
/*
public static int divide(int a, int b){
return true;
}
*/

//可以:但是具体的方法体中编写的代码无法满足当前的需求
/*
public static int divide(int a, int b){
return 1;
}
*/

/*
public static int divide(int a, int b){
int c = a / b;
return c;
}
*/

public static int divide(int a, int b){
// System.out.println("hello");
return a / b;
}
}
/*
深入return语句
* 带有return关键字的java语句只要执行,所在的方法执行结束。
* 在同一个作用域当中,return语句下面不能编写任何代码,因为这些代码永远都执行不到。所以编译报错。
*/

public calss MethodTest09
{
public static void main(String[] args){
int retValue = m();
System.out.println(retValue);

//编译错误:调用方法,方法名后面有括号。
// System.out.println(m);
}

//编译报错:缺少返回语句,以下程序编译器认为无法百分百保证"return 1;"会执行。
/*
public static int m(){
int a = 10;
if(a > 3){ //编译器不知道a大不大于3
return 1;
}
*/

//以下程序可以保证"return 1;" 或 "return 0;"执行。编译通过。
/*
public static int m(){
int a = 10;
if(a > 3){ //编译器不知道a大不大于3
return 1;
}else{
return 0;
}
*/

//可以,和以上方法完全相同
public static int m(){
int a = 10;
if(a > 3){  //编译器不知道a大不大于3
return 1;
}
return 0;
}

public static int m(){
int a = 10;
if(a > 3){  //编译器不知道a大不大于3
return 1;
//这里不能编写代码,编译错误,因为无法访问语句
System.out.println("Hello");
}
//这里的代码可以
System.out.println("hello");
return 0;
//编译错误,无法访问到语句
System.out.println("hello");

public static int m(){
return 10 > 3 ? 1 : 0;
}
}
/*
在返回值类型是void的方法当中使用"return ;"语句。
"return ;"语句出现在返回值为void的方法中主要是为了结束该方法
*/

public class MethodTest10
{
public static void main(String[] args){
m();

for(int i = 10; i > 0; i--){
if(i == 2){
return;  //结束的是main方法
}
System.out.println("data: --> " i);
}
System.out.println("Execute Here~");
}

//编译错误:对于结果类型为空的方法,无法返回值
/*
public static void m(){
return 10;
}
*/

/*
public static void m(){
return;
}
*/

public static void m(){
for(int i = 0; i < 10; i++){
if(i == 5){
// return; //不是终止for循环,终止的是m()方法
break;  //终止for循环
}
System.out.println(i);
}
System.out.println("Hello world");
}
}

 

1.5 方法内存分配原理

/*
方法在执行过程当中,在JVM中的内存是如何分配的呢,内存是如何变化的?
1、方法只定义,不调用,是不会执行的,并且在JVM也不会给该方法分配运行所属的“内存空间”。只有在调用这个方法的时候,才会动态的给这个方法分配所属的内存空间。

2、在JVM划分上有这样的三块主要的内存空间(当然除了这三块之外还有其它的内存空间):
* 方法区内存
* 堆内存
* 栈内存

3、关于栈数据结构:
* 栈:stack,是一种数据结构
* 数据结构反应的是数据的存储形态
* 数据结构是独立的学科,不属于任何编程语言的范畴,只不过在大多数编程语言当中要使用数据结构
* 作为程序员需要提前精通:数据结构 + 算法 【计算机专业必修一门课程】
* java程序员在不精通数据结构和算法的前提下,也可能进行java开发,因为java有一套庞大的类库支撑
* 常见的数据结构:
- 数组
- 队列
- 栈
- 链表
- 二叉树
- 哈希表/散列表

4、方法代码片段存在哪里?方法执行的时候执行过程的内存在哪里分配?
* 方法代码片段属于.class字节码文件的一部分,字节码文件在类加载的时候,将其放到了方法区当中,所以JVM中的三块主要的内存空间中方法区内存最先有数据。存放了代码片段。
* 代码片段虽然在方法区内存当中只有一份,但是可以被重复调用。每一次调用这个方法的时候,需要给该方法分配独立的活动场所,在栈内存中分配。 【栈内存中分配方法运行的所属内存空间】

5、方法在调用的时候,会给该方法分配独立的内存空间,在栈中分配,此时发生压栈动作,方法执行结束之后,给该方法分配的内存空间全部释放,此时发生弹栈动作。
* 压栈:给方法分配内存
* 弹栈:释放该方法的内存空间

6、局部变量在“方法体”中声明。局部变量在运行阶段内存在栈中分配。
*/


public class MethodTest11
{
public static void main(String[] args){

}
}
 

 

 

 

1.6 方法执行内存分析

//注意:在EditPlus当中,字体颜色为红色的表示一个类的名字,并且这个类在JavaSE类库中是自带的。
//我们自己定义的类MethodTest01,字体颜色是黑色,是标识符
//其实JavaSE类库中自带的类,例如:String.class、System.class,这些都是标识符。
//只要是类名就一定是标识符。

//重点:方法调用的时候,在参数传递的时候,实际上传递的是变量中保存的那个“值”传过去了

public class MethodTest01
{
public static void main(String[] args){
int a = 10;
int b = 20;
int retValue = sumInt(a, b);
System.out.println("retValue = " + retValue);
}

public static int sumInt(int i, int j){
int result = i + j;
int num = 3;
int retValue = divide(result, num);
return retValue;
}

public static int divide(int x, int y){
int z = x / y;
return z;
}
}

/*
画图依据:
1、只要涉及到参数传递的问题,传递的是变量中保存的值
2、画图的时候,必须遵循“方法自上而下的顺序依次执行”这个原则。
*/
 

 

 //分析以下程序的输出结果 【画图分析】

//画图
public class MethodTest02
{
public static void main(String[] args){
int i = 10;
method(i);
System.out.println("main --> " + i);
}

public static void method(int i){
i++;
System.out.println("method --> "+ i);
}
}
 

 

 

2 方法重载机制

2.1 方法重载机制引入

/*
以下代码不使用方法重载机制,不使用overload,分析程序存在的缺点?
1、sumInt, sumLong, sumDouble方法虽然功能不同,但是功能是相似的。都是求和在以下程序当中功能相似的方法,分别起了三个不同的名字,这对程序员来说,调用方法的时候不方便,程序员需要记忆更多的方法,才能完成调用。 【不方便】

有没有这样的一种机制:
功能虽然不同,但是功能相似的时候,有没有这样的一种机制,可以让程序员使用这些方法的时候就像在使用同一个方法一样,这样程序员以后编写代码比较方便,也不需要记更多的方法名。
有这种机制:方法制裁机制/Overload
*/

public class OverloadTest01
{
public static void main(String[] args){
//调用方法
int result1 = sumInt(1, 2);
System.out.println(result1);

double result2 = sumDouble(1.3, 2.0);
System.out.println(result2);

long result3 = sumLong(1L, 2L);
System.out.println(result3);
}

//定义一个方法,可以计算同修int类型数据的和
public static int sumInt(int a, int b){
return a + b;
}

//定义一个方法,可以计算两个double类型的数据的和
public static double sumDouble(double a, double b){
return a + b;
}

//定义一个方法,可以计算两个long类型的数据的和
public static long sumLong(long a, long b){
return a + b;
}

//最终希望达到的效果是:程序员在使用上面的三个相似的方法的时候,就像在用一个方法一样。
//Java支持这种机制
}
该程序还是一个体验程序,体验一下方法重载的优点:
* 程序员调用方法的时候,比较方便,虽然调用的是不同的方法,但是就像感觉在使用一个方法一样。不需要记忆更多的方法名。

前提:功能相似的时候,方法名可以相同。

但是:功能不同的时候,尽可能让这两个方法的名字不同。



public class OverloadTest
{
public static void main(String[] args){
//调用方法的时候就像在使用一个方法一样
System.out.println(sum(1, 2));  //参数的类型不同,对应调用的方法不同,此时区分方法不再依靠方法名了,依靠的是参数的数据类型
System.out.println(sum(1.0, 2,0));
System.out.println(sum(1L, 2L));
}

//以下三个方法构成了方法重载机制
public static int sum(int a, int b){
return a + b;
}

public static long sum(long a, long b){
return a + b;
}

public static double sum(double a, double b){
return a + b;
}
}

 

2.2 方法重载使用

1、方法重载又被称为:overload

2、什么时候考虑使用方法重载?
* 功能相似的时候,尽可能让方法名相同。
[但是:功能不同/不相似的时候,尽可能让方法名不同。]

3、什么 条件满足之后构成了方法重载?
* 在同一个类当中
* 方法名相同
* 参数列表不同:
- 数量不同
- 顺序不同
- 类型不同

4、方法重载和什么有关系,和什么没有关系
* 方法重载和方法名+参数列表有关系
* 方法重载和返回值类型无关和修饰符列表无关


public class OverloadTest03
{
public static void main(String[] args){
//以下两个方法构成重载
public static void m1(){}
public static void m1(int a){}

//以下两个方法构成重载
public static void m2(int a, double b){}
public static void m2(double a, int b){}

//以下两个方法构成重载
public static void m3(int x){}
public static void m3(double x){}

//编译错误:以下不是方法重载,是发生了方法重复了
/*
public static void m4(int a, int b){}
public static void m4(int b, int a){}
*/

/*编译报错
public static void x(){}
public static int x(){}
*/

/*
void y(){}
public static void y(){}
/*
}
}

 

2.3 方法重载应用

//OverloadTest04.java 文件中代码如下
/*
方法重载的具体应用
*/

public class OverloadTest04
{
public static void main(String[] args){
/*
System.out.println("Hello World");
System.out.pirntln(10);
System.out.println(true);
*/

U.p(10);
U.p(238.8);
U.p("xiaohong");
U.p('a');
U.p(true);
工具.打印("xiaohong");
}

}


//U.java 文件中代码如下
//自定义类
public class U
{
public static void p(byte b){
System.out.println(b);
}

public static void p(short b){
System.out.println(b);
}

public static void p(int b){
System.out.println(b);
}

public static void p(long b){
System.out.println(b);
}

public static void p(float b){
System.out.println(b);
}

public static void p(double b){
System.out.println(b);
}

public static void p(char b){
System.out.println(b);
}

public static void p(boolean b){
System.out.println(b);
}

public static void p(String b){
System.out.println(b);
}
}


//工具.java 文件中的代码如下
public class 工具
{
public static void 打印(byte b){
System.out.println(b);
}

public static void 打印(short b){
System.out.println(b);
}

public static void 打印(int b){
System.out.println(b);
}

public static void 打印(long b){
System.out.println(b);
}

public static void 打印(float b){
System.out.println(b);
}

public static void 打印(double b){
System.out.println(b);
}

public static void 打印(char b){
System.out.println(b);
}

public static void 打印(boolean b){
System.out.println(b);
}

public static void 打印(String b){
System.out.println(b);
}
}

 

3 方法的递归

3.1 递归的引入

1、什么是递归?
方法自身调用自身。
a(){
a();
}

2、递归是很耗费栈内存的,递归算法可以不用的时候尽量别用。

3、以下程序运行的时候发生了这样的一个错误 【不是异常,是错误Error】
java.lang.StackOverflowError
栈内存溢出错误。
错误发生无法挽回,只有一个结果,就是JVM停止工作。

4、递归必须有结束条件,没有结束条件一定会发生栈内存溢出错误。

5、递归即使有了结束条件,即使结束条件是正确的,也可能发生栈溢出错误,因为递归的太深了

注意:
递归可以不使用尽量别用。
但是有些情况下该功能的实现必须依靠递归方式。例如:目录拷贝。


public class RecursionTest01
{
public static void main(String[] args){
System.out.println("main begin");
//调用doSome方法
doSome();
System.out.println("main over");
}

//以下的代码片段虽然只有一份
//但是可以被重复的调用,并且只要调用doSome方法就会在栈内存中新分配一块所属的内容空间
public static void doSome(){
System.out.println("doSome begin");
doSome();  //这行代码不结束,下一行程序是不能执行的。
System.out.println("doSome over");
}
}

 

3.2 递归的使用

/*
不使用递归,计算1~N的和
*/

public class RecursionTest02
{

public static void main(String[] args){
/*
//1~4的和
int n = 4;
int sum = 0;
for(int i = 1; i <= 4; i++){
sum += i;
}
System.out.println("sum = " + sum);
*/

//直接调用方法地即可
int n = 4;
int retValue = sum(n);
System.out.println(retValue);

n = 10;
retValue = sum(n);
System.out.println(retValue);
}


//单独的定义一个方法,亮是一个独立的功能,可以完成1~N的求和
public static int sum(int n){
int result = 0;
for(int i = 1; i <= n; i++){
result += i;
}
return result;
}
}
/*
使用递归计算1~N的求和
--> 1 + 2 + 3 + 4
--> 4 + 3 + 2 + 1 【 n的最初值是4,建议采用这种方法
*/

public class RecursionTest03
{
public static void main(String[] args){

//1~4的和
int n = 4;
int retValue = sum(n);
System.out.println(retValue);
}

public static int sum(int n){
//4 + 3 + 2 + 1
if(n == 1){
return 1;
}
return n + sum(n - 1);  //sum(n - 1)这个方法不结束运算是不会执行加法运算的,程序卡在这里了
}
}

//n + sum(n - 1)
//4 + sum(3)
//4 + 3 + sum(2)
//4 + 3 + 2 + sum(1)
//4 + 3 + 2 + 1
 

 

 

3.3 递归的应用

/*
先不使用递归,计算N的阶乘
5的阶乘:
5 * 4 * 3 * 2 * 1
*/


/*
public class RecursionTest04
{
public static void main(String[] args){
int n = 5;
int retValue = method(n);
System.out.println(retValue);
}

public static int method(int n){
int result = 1;
for(int i = n; i > 0; i--){
result *= i;
}
return result;
}
}
*/


//递归方式
public class RecursionTest04
{
public static void main(String[] args){
int n = 5;
int retValue = method(n);
System.out.println(retValue);
}

public static int method(int n){
if(n == 1){
return 1;
}
return n * method(n - 1);
}
}

 

3.4 递归调用原理分析图

 

 

 

 

 

 

posted @   路走  阅读(29)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示