• 【Java SE】“方法”论 — 《方法的重载与递归》


    目录

    1.方法的重载

    1.1为什么需要方法重载

    1.2方法重载概念

    1.3方法签名

    2. 递归

    2.1递归的概念

    2.2递归执行过程分析

    2.3递归练习

    (1)按顺序打印一个数字的每一位(例如 1234 打印出 1 2 3 4)

    (2)递归求 1 + 2 + 3 + ... + 10

    (3)写一个递归方法,输入一个非负整数,返回组成它的数字之和. 例如,输入 1729, 则应该返回1+7+2+9,它的和是19

    (4)求斐波那契数列的第 N 项

    2.4递归的效率为什么不高


      

    1.方法的重载

    1.1为什么需要方法重载

    先来实现一个求两个整数的和的方法。

    1. public static int add(int n , int k) {
    2. return n + k;
    3. }
    4. public static void main(String[] args) {
    5. int x = 10;
    6. int y = 20;
    7. int ret1 = add(x, y);
    8. System.out.println(ret1);
    9. }

    代码结果:

    现在需求变了,需要求两个小数的两个整数的和。如果直接调用之前的整数加法函数的话就会出现错误。

    1. public static int add(int n , int k) {
    2. return n + k;
    3. }
    4. public static void main(String[] args) {
    5. int x = 10;
    6. int y = 20;
    7. int ret1 = add(x, y);
    8. double a = 12.5;
    9. double b = 13.4;
    10. double ret2 = add(a, b);
    11. System.out.println(ret1);
    12. System.out.println(ret2);
    13. }

    一个方法的参数个数个数必须相同,返回类型也必须一致,这才是一个正确的方法。

    上面代码计算小数和的时候,调用了整数加法的方法,类型明显不一致,所以才会报错。

    如果要解决的话,就需要写一个小数加法的方法。

    1. public static int addInt(int n , int k) {
    2. return n + k;
    3. }
    4. public static double addDouble(double n , double k) {
    5. return n + k;
    6. }
    7. public static void main(String[] args) {
    8. int x = 10;
    9. int y = 20;
    10. int ret1 = addInt(x, y);
    11. double a = 12.5;
    12. double b = 13.4;
    13. double ret2 = addDouble(a, b);
    14. System.out.println(ret1);
    15. System.out.println(ret2);
    16. }

    代码结果:

    需求虽然是解决了,但是需要提供许多不同的方法名,而取名字本来就是让人头疼的事情。那能否将所有的名字都给成 add 呢?


    1.2方法重载概念

    在Java中,如果多个方法的名字相同,参数列表不同,则称该几种方法被重载了
     

    1. public static int play(int x, int y) {
    2. return x > y ? x : y;
    3. }
    4. public static double play(double x, double y) {
    5. return x > y ? x : y;
    6. }
    7. public static double play(double x, double y, double z) {
    8. double MaxDouble = x > y ? x : y;
    9. return MaxDouble > z ? MaxDouble : z;
    10. }
    11. public static void main(String[] args) {
    12. int ret1 = play(10, 20);
    13. double ret2 = play(12.2,12.3);
    14. double ret3 = play(1.1, 1.2, 1.3);
    15. System.out.println(ret1);
    16. System.out.println(ret2);
    17. System.out.println(ret3);
    18. }

    代码结果:

     可以看到上面代码的三个方法名称相同,调用的时候名称也相同,只是参数和返回类型不相同。

    注意:

    1. 方法名必须相同
    2. 参数列表必须不同(参数的个数不同、参数的类型不同、类型的次序必须不同)
    3. 与返回值类型是否相同无关
    4. 编译器在编译代码时,会对实参类型进行推演,根据推演的结果来确定调用哪个方法参数的类型一定不能相同
       

    现在来解决上面求小数加法的问题。

    1. public static int add(int n , int k) {
    2. return n + k;
    3. }
    4. public static double add(double n , double k) {
    5. return n + k;
    6. }
    7. public static void main(String[] args) {
    8. int x = 10;
    9. int y = 20;
    10. int ret1 = add(x, y);
    11. double a = 12.5;
    12. double b = 13.4;
    13. double ret2 = add(a, b);
    14. System.out.println(ret1);
    15. System.out.println(ret2);
    16. }

    代码结果:


    1.3方法签名

    方法签名即:经过编译器编译修改过之后方法最终的名字。具体方式:方法全路径名+参数列表+返回值类型,构成方法完整的名字。
     

    1. public static int sum(int x, int y){
    2. return x + y;
    3. }
    4. public static double sum(double x, double y){
    5. return x + y;
    6. }
    7. public static void main(String[] args) {
    8. System.out.println(sum(1, 2));
    9. System.out.println(sum(1.5, 2.5));
    10. }

    代码结果:

     上述代码经过编译之后,然后使用JDK自带的javap反汇编工具查看,具体操作:

    1. 先对工程进行编译生成.class字节码文件
    2. 在控制台中进入到要查看的.class所在的目录
    3. 输入:javap -v 字节码文件名字即可

    2. 递归

    2.1递归的概念

    一个方法在执行过程中调用自身, 就称为 "递归"

    递归有一个起始条件, 有一个递推公式.
    例如, 我们求 N!
    起始条件: N = 1 的时候, N! 为 1. 这个起始条件相当于递归的结束条件.
    递归公式: 求 N! , 直接不好求, 可以把问题转换成 N! => N * (N-1)!
     

    递归的必要条件

    1. 将原问题划分成其子问题,注意:子问题必须要与原问题的解法相同
    2. 递归出口
       

    代码示例:求n的阶乘

    1. public static int fac(int num) {
    2. if (num == 1) {//1的阶乘就是1 - 直接返回1就可以
    3. return 1;
    4. } else {
    5. //大于1的情况
    6. int recur = num * fac(num - 1);//调用自身
    7. return recur;
    8. }
    9. }
    10. public static void main(String[] args) {
    11. int num = 3;
    12. int ret = fac(num);
    13. System.out.println(ret);
    14. }

    代码结果:

    2.2递归执行过程分析
     

    求n的阶乘

    1. public static int factor(int n) {
    2. System.out.println("函数开始, n = " + n);
    3. if (n == 1) {
    4. System.out.println("函数结束, n = 1 ret = 1");
    5. return 1;
    6. }
    7. int ret = n * factor(n - 1);
    8. System.out.println("函数结束, n = " + n + " ret = " + ret);
    9. return ret;
    10. }
    11. public static void main(String[] args) {
    12. int n = 3;
    13. int ret = factor(n);
    14. System.out.println("ret = " + ret);
    15. }

    代码结果:

     

    执行过程图:

    2.3递归练习
     

    (1)按顺序打印一个数字的每一位(例如 1234 打印出 1 2 3 4)

    1. public static void add(int n) {
    2. if (n > 9) {
    3. add(n / 10);
    4. }
    5. System.out.println(n % 10);
    6. }
    7. public static void main(String[] args) {
    8. int n = 123;
    9. add(n);
    10. }

    代码结果:

     

    (2)递归求 1 + 2 + 3 + ... + 10

    1. public static int func(int n) {
    2. if (n == 1) {
    3. return 1;
    4. }else {
    5. return n + func(n - 1);
    6. }
    7. }
    8. public static void main(String[] args) {
    9. int num = 10;
    10. int ret = func(num);
    11. System.out.println(ret);
    12. }

    代码结果:

    (3)写一个递归方法,输入一个非负整数,返回组成它的数字之和. 例如,输入 1729, 则应该返回1+7+2+9,它的和是19

    1. public static int sum(int num) {
    2. if (num <= 9) {
    3. return num;
    4. }else {
    5. return num % 10 + sum(num / 10);
    6. }
    7. }
    8. public static void main(String[] args) {
    9. int n = 123;
    10. int ret = sum(n);
    11. System.out.println(ret);
    12. }

    代码结果:

    (4)求斐波那契数列的第 N 项
     

    1. public static int fib(int n) {
    2. if (n == 1 || n == 2) {
    3. return 1;
    4. }
    5. return fib(n - 1) + fib(n - 2);
    6. }
    7. public static void main(String[] args) {
    8. System.out.println(fib(1));
    9. System.out.println(fib(2));
    10. System.out.println(fib(3));
    11. System.out.println(fib(4));
    12. System.out.println(fib(5));
    13. System.out.println(fib(6));
    14. }

    代码结果:

     

    2.4递归的效率为什么不高

     可以根据这张图看出,相同的次数调用了不止一次。每一次调用。都会进行一次运算,调用的多了,运算效率也就降低了。

    注意:对于斐波那契数列来说不要使用递归来写

    在解决斐波那契数列问题的时候,可以采用迭代(循环)来解决,效率回比递归块。并且以后在解决问题的时候,如果问题本身不是特别的复杂,就不建议使用递归,而是要使用迭代(循环)。

  • 相关阅读:
    电脑桌面删除的文件回收站没有,电脑上桌面删除文件在回收站找不到怎么办
    视频汇聚/视频云存储/视频监控管理平台EasyCVR分发rtsp流起播慢优化步骤详解
    Linux压缩、解压缩以及打包命令
    hook函数之useEffect的使用——自定义hook函数网络请求——
    CMT2380F32模块开发9-可编程计数阵列 PCA例程
    算力,承载AI无限可能
    Java项目:SSM教师师资管理系统
    GIT分布式版本控制系统 | 命令讲解入门
    基于深度学习的图像识别技术研究
    Spring Boot 应用的热部署配置
  • 原文地址:https://blog.csdn.net/m0_63033419/article/details/126109194