-
可以初步简单的把Java方法理解为类似于C语言中的函数
-
类、方法、局部变量的关系
其中类:大驼峰,方法和变量都是小驼峰
-
方法定义
修饰限定符 返回值类型 方法名称([参数类型 形参…]){
方法体代码;
[return 返回值];
}
①修饰符:现阶段直接使用public static为固定搭配
②再Java中,方法不能嵌套定义,方法必须写在类中,没有方法声明这种说法(不像C语言,C语言有函数声明) -
方法调用的过程:
调用的方法: 方法名(参数)
调用方法—>传递参数---->找到方法地址---->执行被调方法的方法体----->被调方法结束返回---->回到主调方法继续往下执行
定义方法的时候,不会执行方法的代码,只有调用方法的时候才会执行,一个方法可以被多次调用。 -
方法的执行实在一块内存当中的,这块内存叫做栈。
方法的调用是在栈上的,当方法遇到return or 右花括号},代表当前方法结束了,对应方法开辟的栈帧回收了。
public static int addFun(int a, int b) {
return a + b;
}
public static void main(String[] args) {
int a = 10;
int b = 20;
int ret = addFun(a,b);
System.out.println(ret);
}
关于代码的执行过程:
首先开辟main方法的空间,并且为变量a,b分配地址,下一步执行addFun方法,即为addfun方法开辟内存空间,知乎在addFun方法的内存中为形参a和b开辟空间,遇到return语句,当前方法结束,即将方法开辟的栈帧回收,最后main方法也结束了,main方法开辟的栈帧也被回收。
-
实参和形参的关系
在Java中,实参的值永远都是拷贝到形参中,实参和形参的本质是2个实体,即相当于值传递,而不是地址传递,Java没有指针,所以利用目前所学的知识可能无法对实参a和b利用方法进行值交换,解决的办法是:把a和b放到堆上,学习类和对象之后可以解决这个问题。 -
方法重载
在Java中,如果多个方法的名字相同,参数列表不同,则称该几种方法被重载了。
构成方法重载:
①:方法名称必须相同
②:方法的参数列表不用(参数的个数,参数的类型,参数的顺序)
③:与返回值类型是否相同无关
两个方法如果仅仅知识因为返回值的类型不同,是不能构成重载的
编译器在编译代码的时候,会对实参类型进行推演,根据推演的结果来确定调用哪个方法,根据传的参数取匹配
为什么可以方法重载?---->了解方法签名。 -
方法递归
递归就是①自己调用自己②有一个终止条件(起始条件)
最难的地方:如何确定递推公式 -
循环写和递归写的区别
递归的好处:代码少,但不好书写
循环的好处:容易理解,但是代码比较多
递归浪费的空间会比较多,因为每调用一次方法要开内存,容易把栈挤爆(栈溢出) -
关于斐波那契数列,建议使用循环的方式求解,因为使用递归会有大量的重复计算—>过渡到二叉树。
-
递归求 N 的阶乘
分析:以10为例,求10的阶乘就是求10乘以9的阶乘,求9的阶乘就是求9乘以8的阶乘,…最后乘到1(出口)。
public static int fun1(int n){
//递归求 N 的阶乘
if (n == 1){
return 1;
}else {
return n*fun1(n - 1);
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
System.out.println(fun1(n));
}
- 递归求 1 + 2 + 3 + … + 10,递归求和
分析:1加到10,等于10 + 1加到9, 等于10 + 9 + 1加到8,以此类推,等于加到1(出口)。
public static int fun2(int n) {
if (n == 1){
return 1;
}else {
return n + fun2(n - 1);
}
}
public static void main(String[] args) {
System.out.println(fun2(10));
}
- 递归打印数字的每一位
分析:如果数字是1234,如果用循环做,只能打印出4 3 2 1,要想打印出1 2 3 4,则用递归,如果数字小于10,则直接打印,否则1234,返回123,打印4,返回12,打印3,返回1,打印2,打印1,归。
public static void fun3(int n){
//递归打印数字的每一位
if (n < 10){
System.out.println(n);
}else {
fun3(n / 10);
System.out.println(n % 10);
}
}
public static void main(String[] args) {
fun3(1234);
}
- 写一个递归方法,输入一个非负整数,返回组成它的数字之和
分析:如果只有1位数的话,直接返回那位数,如果是多位数,则先对10取余,得到尾数位,再除以10,得到新的数,重复操作得到新的尾数位并相加。
public static int fun5(int n){
if (n < 10) {
return n;
}else {
return n % 10 + fun5(n / 10);
}
}
public static void main(String[] args) {
//写一个递归方法,输入一个非负整数,返回组成它的数字之和
System.out.println(fun5(123));
}
- 递归求斐波那契数列的第 N 项
分析:1 1 2 3 5 8,斐波那契数列就是第1项和第2项都是1,其余项等于前2项相加。
public static int fun4(int n){
if (n == 1 || n == 2){
return 1;
}else {
return fun4(n - 1) + fun4(n - 2);
}
}
public static void main(String[] args) {
// 递归求斐波那契数列的第 N 项
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int ret = fun4(n);
System.out.println(ret);
}
递归解答斐波那契数列会出现很多重复的计算,可以使用循环的方式来求斐波那契数列的问题,避免出现冗余运算。
- 汉诺塔问题
分析:假如只有1个盘子,则直接将盘子从pos1,移动到pos3(递归出口);如果有n个盘子,则先将n-1个盘子从pos1借助pos3移动到pos2上,此时pos1上只剩下1个盘子,直接移动到pos3;再将pos2上的n-1个盘子借助pos1移动到pos3。汉诺塔移动的次数为2的n次方-1。
public static void hanuota(int n, char pos1, char pos2, char pos3){
if (n == 1) {
move(pos1,pos3);
return;
}else {
hanuota(n-1,pos1,pos3,pos2);
move(pos1,pos3);
hanuota(n-1,pos2,pos1,pos3);
}
}
public static void move(char a, char b){
System.out.println(a + "-->" + b);
}
public static void main(String[] args) {
//汉诺塔问题
hanuota(3,'A', 'B', 'C');
}