目录
1.方法的概念和使用
1.1什么是方法
Java中的方法和C语言中的函数十分类似,方法本质上就是一个代码片段
方法本身是对某个功能的抽象
- 是能够模块化的组织代码(当代码规模比较复杂的时候).
- 做到代码被重复使用, 一份代码可以在多个位置使用.
- 让代码更好理解更简单.
- 直接调用现有方法开发, 不必重复造轮子.
1.2方法定义
方法语法格式
// 方法定义
修饰符 返回值类型 方法名称([参数类型 形参 ...]){
方法体代码;
[return 返回值];
}
注意事项
-
修饰符:现阶段直接使用public static 固定搭配
-
返回值类型:如果方法有返回值,返回值类型必须要与返回的实体类型一致,如果没有返回值,必须写成
void -
方法名字:采用小驼峰命名
-
参数列表:如果方法没有参数,()中什么都不写,如果有参数,需指定参数类型,多个参数之间使用逗号隔开
-
方法体:方法内部要执行的语句
-
在java当中,方法必须写在类当中
-
在java当中,方法不能嵌套定义
-
在java当中,没有方法声明一说
1.3 方法调用的执行过程
方法调用过程
调用方法—>传递参数—>找到方法地址—>执行被调方法的方法体—>被调方法结束返回—>回到主调方法继续往下
执行
注意事项
- 定义方法的时候, 不会执行方法的代码. 只有调用的时候才会执行.
- 一个方法可以被多次调用.
1.4 实参和形参的关系
形参:形参的名字可以随意取,对方法都没有任何影响,形参只是方法在定义时需要借助的一个变量,用来保存方法在调用时传递过来的值。
形参只是实参的一份临时拷贝
例:两数相加
public static int add(int a, int b){
return a + b;
}
add(2, 3); // 2和3是实参,在调用时传给形参a和b
过程:先将2,3两个整形分别传递给形参a和b,然后到了方法体内进行计算,得出的返回值带回到sum中
注意:在Java中,实参的值永远都是拷贝到形参中,形参和实参本质是两个实体
例: 交换两个整型变量
public class TestMethod {
public static void main(String[] args) {
int a = 10;
int b = 20;
swap(a, b);
System.out.println("main: a = " + a + " b = " + b);
}
public static void swap(int x, int y) {
int tmp = x;
x = y;
y = tmp;
System.out.println("swap: x = " + x + " y = " + y);
}
}
// 运行结果
swap: x = 20 y = 10
main: a = 10 b = 20
在main输出的a和b并没有因为执行了方法后将数据交换了
原因:实参a和b是main方法中的两个变量,其空间在main方法的栈(一块特殊的内存空间)中,而形参x和y是swap方法中的两个变量,x和y的空间在swap方法运行时的栈中,因此:实参a和b 与 形参x和y是两个没有任何关联性的变量,在swap方法调用时,只是将实参a和b中的值拷贝了一份传递给了形参x和y,因此对形参x和y操作不会对实参a和b产生任何影响。
1.5没有返回值的方法
方法的返回值是可选的. 有些时候可以没有的,没有时返回值类型必须写成void
class Test {
public static void main(String[] args) {
int a = 10;
int b = 20;
print(a, b);
}
public static void print(int x, int y) {
System.out.println("x = " + x + " y = " + y);
}
如果没有返回值时,函数返回类型不写void就会报错
1.6作用域和生命周期
作用域:在当前花括号{
}
内
方法的生命周期:方法调用开始创建,调用结束时销毁
2.方法重载
我们在一个作用域中不能定义两个形同名称的变量,不能定义两个相同的标识符,但是我们可以在类中定义方法名相同的方法
2.1方法签名
方法签名即:经过编译器编译修改过之后方法最终的名字。具体方式:方法全路径名+参数列表+返回值类型 构成方法完整的名字。
其中add:(I I)I和add:(D D)D才是add方法的真名
方法签名中的一些特殊符号说明:
2.2重载的使用
这里举例一个重载的add函数,此时的add不仅能计算整数相加的值,还能计算小数相加,在调用add函数时,编译器就会自动询问要用哪种方式去调用add,
2.3错误的重载
当方法签名完全一样时会报错
只修改形参名称,不会修改方法签名,所以还是会报错
只修改返回值类型,是不可以的
2.4重载触发的要求
触发重载的要求
-
方法名称相同
-
形参列表不同(类型,个数,顺序)
-
返回值不做要求,可以一样也可以不一样,但是只修改返回值类型,是不可可以触发重载的,也就是说只修改返回值类型,方法还是同一个方法
3.递归
之前在C语言中我们已经研究过了递归这个问题
下面我们再去回顾一下
3.1递归概念
简单的说:递归就是方法自己调用自己 ,每次调用时传入不同的变量 .递归有助于编程者解决复杂的问题 ,同时可以让代码变得简洁
3.2递归的使用
代码示例: 递归求 N 的阶乘
public static int func(int n){
if(n==1){
return 1;
}else {
return n*func(n-1);
}
}
public static void main(String[] args) {
Scanner scan=new Scanner(System.in);
int num= scan.nextInt();
System.out.println(func(num));
}
递归过程:
3.3递归出现的问题
栈溢出问题:当递归死循环后或者递归不结束就会把栈区占满溢出
3.4不需要递归的题目
求斐波那契数列可以直接写循环去结题,如果硬要去写递归反而会加大运算次数,重复计算没有必要的内容
递归解题:
public static int fib(int n) {
if (n == 1 || n == 2) {
return 1;
}
return fib(n - 1) + fib(n - 2);
}
当我们求 fib(45) 的时候发现, 程序执行速度极慢. 原因是进行了大量的重复运算,你会发现去计算第45个斐波那契数字时fib(1)被计算了1134903170次.
所以遇到这种写递归解题反而没有正常使用循环结题高效的情况下,就不要去用递归去结题了
循环解法:
public static void main(String[] args) {
int num1=1;
int num2=1;
int num3=0;
for (int i = 3; i <= 45; i++) {
num3=num1+num2;
num1=num2;
num2=num3;
}
System.out.println(num3);
}