Java方法 - 方法重载 - 递归

Java方法✔️前言一,方法的基本用法方法的定义规则方法的执行过程Java理解方法(函数)栈帧实参和形参的关系二,方法的重载使用重载的目的重载的规则三,递归递归公式解决问题递归分析过程代码递归路线图形象分析图递归练习✨总结一,方法的基本用法对于初学者来说,方法的概念是第一次听说,但其实他就类似于C语言中的函数,是一个可以多次使用,并且完成单一功能的代码块。

Java方法

  • ✔️前言
  • 一,方法的基本用法
    • 方法的定义规则
    • 方法的执行过程
      • Java理解方法(函数)栈帧
      • 实参和形参的关系
  • 二,方法的重载
    • 使用重载的目的
    • 重载的规则
  • 三,递归
    • 递归公式解决问题
    • 递归分析过程
      • 代码递归路线图
      • 形象分析图
    • 递归练习
  • ✨总结

一,方法的基本用法

对于初学者来说,方法的概念是第一次听说,但其实他就类似于C语言中的函数,是一个可以多次使用,并且完成单一功能的代码块。

那么,为什么要引入方法的概念呢?

举一个例子演示使用方法进行编程的好处:

例如,编程实现1!~ 5!求和。

如果用普通方法实现,需要使用到循环嵌套技术:

public class Method {    /**     * 求1! ~ 5!的求和     * @param args     */    public static void main(String[] args) {        int sum = 0;        for (int i = 1; i <= 5; i++) {            int ret = 1;            for (int j = 1; j <= i; j++) {                ret *= j;            }            sum += ret;        }        System.out.println(sum);    }}   

使用嵌套循环比较容易写出bug,而利用方法就可以有效避免,并且能将功能单一化:

public class Method {    /**     * 求n的阶乘     * @param args     */    public static int fac(int n) {        int ret = 1;        for (int i = 1; i <= n; i++) {            ret *= i;        }        return ret;    }    /**     * 求1~5的阶乘之和     * @param args     */    public static int sumFac(int n) {        int sum = 0;        for (int i = 1; i <= n; i++) {            sum += fac(i);        }        return sum;    }    public static void main(String[] args) {        int n = 5;        int ret = sumFac(n);        System.out.println(ret);    }}  

使用两个不同的方法完成两个独立的功能,这种写法更加体现代码的可读性和可维护性~


方法的定义规则

在Java中的使用规则需要用到类和对象的概念,但那不是本文主要讲述的内容,所以这里不多赘述,只需要知道初学者大部分使用的方法都有固定的写法:

例如:

public class Method {    public static void func() {        System.out.println("hehe");    }    public static void main(String[] args) {        func();    }}

这里的func方法采用的写法就是
public + static + 返回类型 + 方法名(参数列表)

我们只需要知道他固定的写法格式即可,具体含义在学习了类和对象即可理解,有兴趣的小伙伴也可以看博主的专栏JavaSE

里面记录了JavaSE需要掌握的全部内容~

注意:

  • 参数列表中必须给出参数的数据类型。
    (可以没有参数)
  • 方法名必须采用小驼峰写法。

总结:

public和static在这里有特殊的含义,但不在本文作详细介绍,有兴趣可以看博主专栏JavaSE。

在方法定义中,可以没有参数,但如果有参数,一定要指明参数类型。

方法定义中,可以没有返回值,但方法定义的返回类型应该是void类型。

方法调用时的参数称为实参,方法定义时的参数称为形参。

方法的定义必须在类当中,但在类当中的具体位置不受约束,可处于代码上下文任意位置。

Java中没有函数声明的概念。

————————————————

方法的执行过程

这里我们需要注意一点,与C语言不同的是,Java中没有函数声明之类的东西,也就是说,我们在写Java代码时,不需要对方法进行声明,这也就意味着,方法的所处的位置是任意的。

我们回忆一下在学习C语言时,函数定义必须在main函数定义之前,否则就需要在使用该函数之前进行函数声明,而Java中因为没有方法声明这种概念,所以也就不需要将方法定义在main函数之前。

下面用一段代码的执行过程分析方法的执行流程:

public class Method {    /**     * 求n的阶乘     * @param n     * @return     */    public static int fac(int n) {        int ret = 1;        for (int i = 1; i <= n; i++) {            ret *= i;        }        return ret;    }    public static void main(String[] args) {        int ret = fac(5);        System.out.println(ret);    }}  

运行结果:

Java方法 - 方法重载 - 递归

我们在这里分析一下代码运行流程:

注意: main函数中fac方法是方法调用,括号里的是实参,方法定义中参数列表里的是形参,实参和形参的个数必须一致,数据类型必须一一对应。

方法调用基本规则:

  1. 方法代码定义时,不会被执行,只有被调用后才会被执行,也就意味着同一个方法可能被执行多次。
  2. 方法在调用时,会将实参临时拷贝给形参。(具体只是可以看图解函数栈帧 - 函数的创建与销毁)。
  3. 参数传递(拷贝)后,就会开始执行方法的代码。
  4. 当方法代码被执行完之后(遇到return)就会返回被调用方法中,继续执行下面的代码。
  5. 一个方法可以被多次调用。

Java理解方法(函数)栈帧

Java是面向对象的语言,其反汇编的封装做得比较完善,所以不容易分析其方法栈帧的原理,所以这里博主通过画图的方式简单介绍即可。

  • 我们知道,任何程序的开端都是main方法,而所有的方法都是在栈上以压栈的形式开辟的。

Java方法 - 方法重载 - 递归

  • 在main方法里调用func方法,则会在栈顶为func方法开辟栈帧空间。

Java方法 - 方法重载 - 递归

  • 当func方法return之后,则销毁func方法的栈帧,并带回返回值交给main方法中调用方法的执行语句。

Java方法 - 方法重载 - 递归

实参和形参的关系

举个简单的例子:交换两个整数

public class Method {    public static void swap(int x, int y) {        int tmp = x;        x = y;        y = tmp;    }    public static void main(String[] args) {        int a = 3;        int b = 5;        System.out.println(a);        System.out.println(b);        swap(a, b);        System.out.println(a);        System.out.println(b);    }}  

运行结果:

Java方法 - 方法重载 - 递归

可以发现,这里无法通过形参的交换而改变实参。

画图解释:

  • 这里有两个实参。

Java方法 - 方法重载 - 递归

  • 将实参做一份临时拷贝给形参

Java方法 - 方法重载 - 递归

  • 通过第三个变量交换形参。

Java方法 - 方法重载 - 递归

  • 交换后

Java方法 - 方法重载 - 递归

交换后形参发生了改变,但实参并没有进行交换,当该swap方法执行完之后,其方法栈帧将会被销毁,也就意味着这个方法什么功能都没能实现。


到这,可能有码友会问,那能不能类似于C语言,进行传址调用呢?

答案是否定的,在Java中没有取地址(&)这种操作,也没有指针的概念,只有类似的引用,所以想要完成这样的交换功能,只能通过引用的方式,但如果要介绍这道题的正确解法,需要用到类和对象以及引用的知识,就不多介绍,有需要的可以去JavaSE专栏找到相应文章。

这里只把相应代码展示,以供参考:

public class Method {    public static void swap(int[] arr) {        int tmp = arr[0];        arr[0] = arr[1];        arr[1] = tmp;    }    public static void main(String[] args) {        int[] arr = {10, 20};        swap(arr);        System.out.println("a = " + arr[0] + " b = " + arr[1]);    }     }   

二,方法的重载

在Java中方法是可以重载的(overload)。

使用重载的目的

用一个简单的例子说明为什么需要重载。

比如:我要写一个加法方法。

public class Method {    public static int add(int x, int y) {        return x + y;    }    public static void main(String[] args) {        int a = 3;        int b = 5;        int ret = add(a, b);        System.out.println(ret);    }}   

这个方法只适用于两个整型的相加,如果我想让三个整型相加或者两个浮点数相加则做不到,必须重新写一个新的方法,其方法名不能和该方法相同。

而方法重载的概念就是改变参数列表,方法名不变,看以下代码:

public class Method {    public static int add(int x, int y, int z) {        return x + y + z;    }    public static int add(int x, int y) {        return x + y;    }    public static void main(String[] args) {        int a = 3;        int b = 5;        int c = 1;        int ret1 = add(a, b);        int ret2 = add(a, b, c);        System.out.println(ret2);    }}   

此时的public static int add(int x, int y, int z)和public static int add(int x, int y)就构成了重载的关系。

无独有偶。

public class Method {    public static double add(double x, double y) {        return x + y;    }    public static int add(int x, int y, int z) {        return x + y + z;    }    public static int add(int x, int y) {        return x + y;    }    public static void main(String[] args) {        int a = 3;        int b = 5;        int c = 1;        int ret1 = add(a, b);        int ret2 = add(a, b, c);//        System.out.println(ret2);        double d1 = 3.4;        double d2 = 2.4;        double ret3 = add(d1, d2);        System.out.println(ret3);    }}

此时的public static double add(double x, double y)和public static int add(int x, int y, int z)以及public static int add(int x, int y)都构成了重载的关系。

这样写代码就可以共用一个函数名,通过不同的参数列表对不同的数据类型实现相同的功能。

重载的规则

  • 方法名必须相同。
  • 参数列表必须不同(个数,类型)。
  • 与返回类型无关。

首先,方法名必须相同,因为实现的是相同的功能,我们可以理解为是同一个方法对于不同数据的衍生处理。

例如:

public class Method {    public static int add1(int x, int y) {        return x + y;    }    public static int add2(int x, int y) {        return x + y;    }    public static void main(String[] args) {        int a = 3;        int b = 5;        int ret1 = add1(a, b);        int ret2 = add2(a, b);        System.out.println(ret1);        System.out.println(ret2);    }}   

此时的add1和add2是完全不同的两个方法,他们不构成重载关系。


满足重载关系的条件还有参数列表的不同,也就是说参数个数,类型,有一个满足不同即可。

最后一点,也是初学者最容易产生误区的一点,方法的返回类型并不能影响重载。

也就是说如果方法名相同,参数列表不同的两个方法,不管返回类型是否一样,都构成重载关系。

而如果方法名相同,参数列表也相同的两个方法,不管返回类型是否一样,都不构成重载关系。

三,递归

以上概念来自百度百科,虽然话术比较官方,但还算言简意赅。

其实简单来说,程序运行时,某一个方法自己调用自己,就被称作递归。

其实递归很好理解,他就类似于我们高中学的"数学归纳法",或者又类似于"通项",我们就是要找出其起始条件,推出递归公式即可完成任务。

递归公式解决问题

public class Method {    public static int fac(int n) {        if (n > 1) {            return n * fac(n - 1);        }else {            return 1;        }    }    public static void main(String[] args) {        int ret = fac(5);        System.out.println(ret);    }}  

运行结果:

Java方法 - 方法重载 - 递归

又比如要求斐波那契数列,我们也可以直接使用递归公式。

public class Method {    public static int fib(int n) {        if (n == 1 || n == 2) {            return 1;        }else {            return fib(n - 1) + fib(n - 2);        }    }    public static void main(String[] args) {        int ret = fib(10);        System.out.println(ret);    }}   

运行结果:

Java方法 - 方法重载 - 递归

递归分析过程

代码递归路线图

递归的过程其实是横向的,接下来画图分析。

就拿阶乘举例:

Java方法 - 方法重载 - 递归

假设给定n为3。

  • 下面展示全过程

Java方法 - 方法重载 - 递归

  • 接下来就是归过程

Java方法 - 方法重载 - 递归

此时就完成了递归的全过程,最终将3!答案6返回给调用方法。


为了方便理解,再用另一种方法描述。

形象分析图

同样还是用阶乘的代码来描述。

如图:

Java方法 - 方法重载 - 递归

假设这是一个阶乘方法的流程,从上至下运行。

遇到递归调用,则重新开辟栈帧然后进入新的栈帧。

Java方法 - 方法重载 - 递归

最后一个fac方法走完之后(遇到return)往回归。

Java方法 - 方法重载 - 递归

这样就完成了递归的内容,并将返回值带回。

说了那么多概念和解释,用几道简单的小例题加以巩固。

递归练习

  • 示例代码1: 按顺序打印出一个数字的每一位(例如 1234 打印出 1 2 3 4)
public class Method {    /**     * 按顺序打印一个数字的每一位(例如 1234 打印出 1 2 3 4)     * @param args     */    public static void print(int n) {        if (n < 10) {            System.out.print(n + " ");        }else {            print(n / 10);            System.out.print(n % 10 + " ");        }    }    public static void main(String[] args) {        print(1234);    }}

代码示例2: 递归求 1 + 2 + 3 + … + 10

public class Method {    /**     * 递归求 1 + 2 + 3 + ... + 10     * @param args     */    public static int sum(int n) {        if (n > 1) {            return n + sum(n - 1);        }else {            return 1;        }    }    public static void main(String[] args) {        int ret = sum(10);        System.out.println(ret);    }}   

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

public class Method {    /**     * 写一个递归方法,输入一个非负整数,返回组成它的数字之和。 例如,输入 1729, 则应该返回1+7+2+9,     * 它的和是19     * @param args     */    public static int sumEveryOne(int n) {        if (n < 10) {            return n;        }else {            return n % 10 + sumEveryOne(n / 10);        }    }    public static void main(String[] args) {        int ret = sumEveryOne(1729);        System.out.println(ret);    }}  

✨总结

本文主要介绍了Java方法的概念和用法,并拓展了Java方法引出的方法重载以及方法递归,希望本文能对大家的学习有帮助,最后求一波三连支持~

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/70217.html

(0)

相关推荐