java语言基础(方法,递归)
1. 方法
为了实现一个功能我们需要编写100行代码,在程序的运行过程中我们不断的要使用这个功能。如果每次都重复编写这100行代码,程序会变得很臃肿,可读性也会非常差。为了解决代码重复编写的问题,我们可以把这个功能提取出来放在一个{}中,并为这个代码起个名字。这样在每次使用这个功能室我们通过这个代码的名字来调用这段代码就可以了,在上述过程中,所提取出来的代码可以被看做是程序中定义的一个方法。程序在需要实现该功能时调用方法即可。
1.1 定义
- 方法即完成特定功能的代码块
- 在很多语言中都有函数的定义,但是在java语言中,我们将其称之为方法
1.2 方法格式
修饰符 返回值类型 方法名(参数类型 参数名1,参数类型 参数名2 …){
方法体;
return 返回值;
}
格式说明:
- 修饰符 比较多,后面会详细介绍。目前使用 public static
- 返回值类型 用于限定返回值的数据类型
- 方法名 就是一个名称,它的存在是为了方便我们调用方法
- 参数类型 限定调用方法时传入参数的数据类型
- 参数名 是一个变量,接收调用方法时传入的参数
- 方法体 完成功能的代码
- return 结束方法以及返回方法指定类型的值
- 返回值 就是功能的结果,由return带回,带回给调用者
1.3 方法调用
需求1:求两个数据之和的案例
两个明确
- 返回值类型 明确功能结果的数据类型
- 参数列表 明确传递参数的个数,以及每一个参数的数据类型
方法调用
- 单独调用,一般来说没有意义,所以不推荐
- 赋值调用,推荐方案
- 输出调用,但是不够好。因为我们可能需要针对结果进行进一步的操作
代码示例:
public class FunctionDemo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入第一个整数:");
int num1 = sc.nextInt();
System.out.println("请输入第二个整数:");
int num2 = sc.nextInt();
int sum = add(num1,num2);
System.out.println(num1+" + "+num2+" = "+sum);
}
public static int add(int num1, int num2) {
int sum = num1 + num2;
return sum;
}
}
需求2:录入学生成绩并输出成绩等级
public class GradeClassify {
public static void main(String[] args) {
boolean sign = true;
int score = 0;
while(sign){
Scanner sc = new Scanner(System.in);
System.out.println("请输入你的成绩0-100:");
if(sc.hasNextInt()){
int num = sc.nextInt();
if(num>=0&&num<=100){
sign = false;
score = num;
}else{System.out.println("输入范围不正确,请重新输入");}
}else{
System.out.println("输入类型不正确,请重新输入");
}
}
Grade gd = new Grade();
gd.ClassifyGrade(score);
}
static class Grade{
public void ClassifyGrade(int score){
if(score>=0&&score<60){
System.out.println("E等");
}
else if(score>=60&&score<=69){
System.out.println("D等");
}
else if(score>=70&&score<=79){
System.out.println("C等");
}
else if(score>=80&&score<=89){
System.out.println("B等");
}
else if(score>=90&&score<=100){
System.out.println("A等");
}
}}
}
1.4 注意事项
- 方法不调用不执行
- 方法与方法是平级关系,不能嵌套定义
- 方法定义的时候参数之间用逗号隔开
- 方法调用的时候不用再传递数据类型。实参可以是常量,也可以是变量
- 如果方法有明确的返回值,一定要由return带回一个值
1.5 方法重载
在同一个类中,允许存在一个以上的同名方法,只要它们的参数列表不同,与返回值无关,不拿返回值类型来区分。参数列表不同有两层含义:
- 参数个数不同
- 参数类型不同
案例:输出多个数字的和
代码示例:
public class SumDemo {
public static void main(String[] args) {
//求多个数相加
double sum=add(1,2.0);
int sum2 = add(1, 2, 3);
int sum3 = add(1, 2, 3, 4);
int sum4 = add(1,2);
System.out.println(sum);
System.out.println(sum2);
System.out.println(sum3);
System.out.println(sum4);
}
//方法重载:允许一个类中可以定义多个同名方法,只要,他们的参数个数或参数的类型,不一样就可以。不能返回值类型来区分
public static int add(int a,int b){
System.out.println("两个int的调用了");
return a+b;
}
public static double add(int a, double b) {
System.out.println("一个int的一个double调用了");
return a + b;
}
public static int add(int a,int b,int c){
return a+b+c;
}
public static int add(int a,int b,int c,int d){
return a+b+c+d;
}
}
1.6 参数传递问题
在调用方法时,有时需要进行参数传递,有两种情况:
- 基本数据类型作为参数传递,属于值传递,就是把实参的值传过去,形参的改变不影响实参。
- 引用类型作为参数传递,属于引用传递,传递的是地址值,形参的改变会影响实参。
案例分析:
public class MyTest {
public static void main(String[] args) {
int a = 10;
int b = 20;
System.out.println("a: " + a + ",b: " + b); // a:10,b:20
change(a,b);
System.out.println("a: " + a + ",b: " + b); // a:10,b:20
int[] arr = {1,2,3,4,5};
change(arr);
System.out.println(arr[1]); // 4
}
public static void change(int a,int b) {
System.out.println("a: " + a + ",b: " + b); // a:10,b:20
a = b;
b = a + b;
System.out.println("a: " + a + ",b: " + b); // a:20,b:40
}
public static void change(int[] arr){
for(int x = 0 ; x < arr.length ; x++){
if(arr[x]%2 == 0){
arr[x] *= 2;
}
}
}
}
2. 递归
方法定义中调用方法本身的现象。递归所体现的是一种拆分合并的思想。
2.1 注意事项
- 要有出口,否则就是死递归(会造成栈溢出)
- 次数不能太多,否则就内存溢出
2.2 案例演示
-
案例一:计算整数的阶乘
public class JieChenDemo { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("请输入整数:"); int num = sc.nextInt(); int ans = jieChen(num); while(num!=0){ if(num!=1){ System.out.print(num+" * "); }else{ System.out.print(num); } num--; } System.out.print(" = "+ans); } public static int jieChen(int num) { //StackOverflowError n过大时 int ans = 0; if(num==1){ ans = 1; }else{ ans = jieChen(num-1)*num; } return ans; } }
-
案例二:兔子问题(斐波那契数列)
有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问第二十个月的兔子对数为多少?
-
递归实现
public class FibonacciDemo { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("请输入斐波那契数列的项数:"); int n = sc.nextInt(); int num = Fibonacci(n); System.out.println("斐波那契数列第"+n+"项为"+num); } public static int Fibonacci(int n){ if(n==1){ return 0; }else if(n==2){ return 1; } return Fibonacci(n-1)+Fibonacci(n-2); } }
-
数组实现
public class FibonacciDemo2 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("请输入斐波那契数列的项数:"); int n = sc.nextInt(); int [] arr = Fibonacci(n); System.out.println("斐波那契数列为:"); System.out.println(Arrays.toString(arr)); } public static int[] Fibonacci(int n) { int [] arr = new int[n]; if(n==1){ arr[0] = 0; }else if(n==2){ arr[0] = 0; arr[1] = 1; }else{ arr[0] = 0; arr[1] = 1; for(int i =2;i<n;i++){ arr[i] = arr[i-1] + arr[i-2]; } } return arr; } }
-