Java中的方法和递归

Java中的方法和递归

方法的定义

示例代码:

public class Demo1 {
    public static void main(String[] args) {
        int num = sum(1,2);
        System.out.println(num);
    }
​
    /**
     *
     * @param a 形参1
     * @param b 形参2
     * @return 形参1和形参2的和
     */
    public static int sum (int a ,int b){
        return a+b;
    }
}

方法是语句的集合,他们在一起执行一个功能。

  • 方法的命名规则与变量一样,首字母小写,其他单词首字母大写。

  • 方法是解决一类问题的步骤的有序组合

  • 方法包含于类或对象中

  • 方法在程序中被创建,在其他地方被调用

方法本意是功能块,就是实现某一个功能的语句集合,我们设计方法的时候最好保持方法的原子性,就是一个方法只完成一个功能,这样有利于程序后期的拓展。

例:System.out.println()

  • System是类。

  • out是对象。

  • println是方法。

  • ()中是方法的参数。

 

方法的结构

示例代码:

public class Demo1 {
    public static void main(String[] args) {
        int a = 1;      //实参1
        int b = 2;      //实参2
        int num = sum(a,b);     //调用方法将实参传送到方法内
        System.out.println(num);
    }
    
    /**
     * @public 修饰符
     * @static 修饰符
     * @int 返回值类型
     * @sum 方法名
     * @param a 定义形参1接收实参1的值
     * @param b 定义形参2接收实参2的值
     * @return 形参1和形参2的和
     */
    public static int sum (int a ,int b){
        //方法内其实是把实参的值赋给形参使用形参进行运算。
        return a+b;
        //方法体
    }
}
  • 修饰符(可选)

    告知编译器如何调用该方法,定义了该方法的访问类型。

  • 返回值类型

    根据设计需求,方法可能会有各种各样的返回值,需要定义返回值的类型,如果没有返回值,则返回值类型为void。

  • 方法名

    方法的实际名称,方法名和参数表共同构成方法签名。

  • 参数类型

    形参,作用域为当前方法内,当方法被调用时需根据方法的形参传递值给参数,这个值被称为实参,在方法中实参的值被赋给形参进行运算。

    • 形参

      在方法被调用时用来接收外部的数据

    • 实参

      调用方法时实际传给方法的数据。

  • 方法体

    包含具体的执行语句,定义该方法的功能。

  • return语句

    如果方法定义有返回值,则需要使用return语句返回对应的数据,return语句的另一个作用是终结方法。

 

方法的调用

Java支持两种调用方法的方式,根据是否有返回值来选择。

  • 当方法返回一个值的时候,方法通常被当作一个值来使用。

    示例代码:

    import java.util.Scanner;
    ​
    public class Demo2 {
        public static void main(String[] args) {
            double a = 0;
            double b = 0;
            Scanner scanner = new Scanner(System.in);
    ​
            while (true) {
                System.out.println("请输入第一个数字:");
                if (scanner.hasNextDouble()) {
                    a = scanner.nextDouble();
                    break;
                } else {
                    System.out.println("您的输入有误,请重新输入。");
                }
            }
    ​
            while (true) {
                System.out.println("请输入第二个数字:");
                if (scanner.hasNextDouble()) {
                    b = scanner.nextDouble();
                    break;
                } else {
                    System.out.println("您的输入有误,请重新输入。");
                }
            }
            System.out.println("两个数中最大的数字为:"+max(a,b)); //调用方法,直接当作一个值使用。
        }
    ​
        public static double max(double a, double b) {
            if (a == b) {
                System.out.print("两个数字相等,结果为:");
                return 0;
            } else if (a > b) {
                return a;
            } else {
                return b;
            }
        }
    }

 

  • 当方法返回值为void的时候,方法的调用一定是一个语句。

    示例代码:

    public class Demo3 {
        public static void main(String[] args) {
            System.out.println("这个方法被当作一个语句执行了");
        }
    }

 

方法的重载

方法的重载就是在一个类中,有相同的方法名称,但形参不同的方法。

示例代码:

public class Demo3 {
    public static void main(String[] args) {
        int a = 10;
        int b = 10;
        double c = 3.14;
        double d = 6.66;
​
        System.out.println(max(c, d));
        System.out.println(max(a, b));
    }
​
    public static int max(int a, int b) {
        if (a > b) {
            return a;
        } else {
            return b;
        }
    }
​
    public static double max(double a, double b) {
        if (a > b) {
            return a;
        } else {
            return b;
        }
    }
}

以上代码使用了方法的重载将使max方法对两个类型的变量都能够使用。

重载规则:

  • 方法名必须相同

  • 方法参数列表必须不同

  • 仅返回类型不同不足以成为方法的重载

  • 方法名相同时,编译器会根据方法的参数个数、类型等逐个去匹配,如果匹配失败则会报错。

 

方法的命令行传参

某些特殊情况下,我们需要在程序运行后再传递给他消息,这需要依靠传递参数给main方法。

示例代码:

package base;
​
public class Demo4 {
    public static void main(String[] args) {
        for (int i = 0; i < args.length; i++) {
            System.out.println(args[i]);
        }
    }
}

编译和运行:

 

可变参数

示例代码:

public class Demo4 {
    public static void main(String[] args) {
        Demo4 demo4 = new Demo4();
        demo4.list(1,3,2,15,15,123,12312415);
    }
​
    public void list(int... a){
        for (int x:a){
            System.out.println(x);
        }
    }
}
  • 从JDK1.5开始,Java支持传递同类型的可变参数给一个方法。

  • 在方法声明中,在指定参数的类型后面加一个省略号...。

  • 一个方法只能指定一个可变参数,它必须是方法的最后一个参数,任何普通的参数必须在它之前。

  • 可变参数也叫做不定项参数,常用于传递不确定边界的数组或集合。

 

递归

递归就是在方法的方法体中调用本方法,也就是调用自己。利用递归可以通过简单的程序解决一些复杂的问题。

递归的能力在于用有限的语句来定义对象的无限集合。

示例代码:

/**
 * 阶乘:1的阶乘:1*1
 * 2的阶乘:2*1
 * 5的阶乘:5*4*3*2*1
 * 10的阶乘:10*9*8*7*6*5*4*3*2*1
 * <p>
 * 计算10的阶乘,并输出结果。
 */
public class Demo5 {
    public static void main(String[] args) {
        System.out.println(factorial(10));
    }
​
    public static int factorial(int n) {
        if (n == 1) {       //递归头
            return 1;
        } else {
            return n * factorial(n - 1);        //递归体
        }
    }
}

递归结构必须包含两个部分,递归头和递归体。

  • 递归头

    什么时候不调用自身方法,如果没有头则死循环,程序栈溢出。

  • 递归体

    什么时候需要调用自身方法。

 

以以上示例代码浅谈递归执行顺序:

  1. 程序开始执行,执行到main方法,并执行到println方法。

  2. println参数中调用了factorial方法代入实参5计算实参的阶乘并返回给println方法。

  3. 程序开始执行最开始的方法调用,调用factorial方法代入实参5赋值给形参n

  4. 执行if语句,开始判断n是否为1。(此时n为5)

  5. if条件不满足,进入else分支,返回n*factorial方法的返回值,factorial方法代入实参n-1。(此处带入4)

  6. 开始第一次递归,factorial方法受到调用,开始执行,代入实参4赋值给形参n

  7. 因不满足if条件(此时n为4),进入else分支开始计算n*factorial方法的返回值,factorial方法代入实参n-1(此处带入3)

  8. 开始第二次递归,factorial方法受到调用,开始执行,代入实参3赋值给形参n

  9. 因不满足if条件(此时n为3),进入else分支开始计算n*factorial方法的返回值,factorial方法代入实参n-1(此处带入2)

  10. 开始第三次递归,factorial方法受到调用,开始执行,代入实参2赋值给形参n

  11. 因不满足if条件(此时n为2),进入else分支开始计算n*factorial方法的返回值,factorial方法代入实参n-1(此处带入1)

  12. 开始第四次递归,factorial方法受到调用,开始执行,代入实参1赋值给形参n

  13. 此时n为1所以if条件满足,执行if中的语句,返回值1。

  14. 第四次递归返回值1返回给第三次递归进行运算,即n * factorial(n - 1),此时factorial(n - 1)的值为1,即计算2 * 1的值。(因第三次递归时n的值为2)

  15. 第三次递归返回值2返回给第二次递归进行运算,即n * factorial(n - 1),此时factorial(n - 1)的值为2,即计算3 * 2的值。(因第二次递归时n的值为3)

  16. 第二次递归返回值6返回给第一次递归进行运算,即n * factorial(n - 1),此时factorial(n - 1)的值为6,即计算4 * 6的值。(因第一次递归时n的值为4)

  17. 第一次递归返回值24返回给最开始的方法调用进行运算,即n * factorial(n - 1),此时factorial(n - 1)的值为24,即计算5 * 24的值。(因最开始我们传入的实参为5)

  18. 方法全部运行结束,返回值5*24的结果,即120。回到主程序,执行System.out.println(120);。

  19. 打印结果120。

 

递归拓展:

Java是利用栈的语言,程序运行在栈中,每个方法、每个变量都在栈中有自己的空间。

递归其实是一种压栈的方法,每递归当前方法一次,储存方法的栈则多压一层,递归结束后栈才会"释压",当栈满时则会溢出,内存崩溃。

所以使用递归的时候一定要小心,递归方法尽量不要有返回值或者基本类型的返回值。如果必须要有,而且特别复杂,则写成多个方法。

posted @   乌鸦の学习  阅读(122)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
点击右上角即可分享
微信分享提示