javaSE- 方法的使用

news2025/1/20 1:51:18

一、方法的基本用法

方法就是一个代码片段. 类似于 C 语言中的 “函数”.
方法存在的意义(不要背, 重在体会):

  1. 是能够模块化的组织代码(当代码规模比较复杂的时候).
  2. 做到代码被重复使用, 一份代码可以在多个位置使用.
  3. 让代码更好理解更简单.
  4. 直接调用现有方法开发, 不必重复造轮子

回忆一个之前写过的代码: 计算 1! + 2! + 3! + 4! + 5!

public static void main(String[] args) {
        int sum = 0;
        for (int i = 1; i <= 5; i++) {
            int tmp = 1;
            for (int j = 1; j <= i; j++) {
                tmp *= j;
            }
            sum += tmp;
        }
        System.out.println("sum = " + sum);
    }

这个代码中使用双重循环, 比较容易写错.
接下来我们可以使用方法来优化这个代码

	/**
     * 计算 n 阶乘
     * @param n
     * @return
     */
    public static int tmp(int n){
        int ret = 1;
        for(int i = 1; i <= n; i++){
            ret = ret * i;
        }
        return ret;
    }
    
    public static void main(String[] args) {
        int sum = 0;
        for (int i = 1; i <= 5; i++) {
            //产生 1 - 5的数
            int ret = tmp(i);//tmp 这个函数就是 计算 n 阶乘
            sum = sum + ret;
        }
        System.out.println("sum = " + sum);
    }

在这里插入图片描述

像上面tmp函数的功能就是计算一个数的阶乘,这就是函数的基本用法,并且这个函数的功能是唯一的

1.1、方法定义语法

// 方法定义
public static 方法返回值 方法名称([参数类型 形参 ...]){
	方法体代码;
	[return 返回值];
}

在这里插入图片描述

1.1.1、代码示例: 实现一个方法实现两个整数相加

	public static int sumAdd(int x, int y){
        return x + y;
    }

    public static void main(String[] args) {
        int a = 10;
        int b = 20;
        int sum = sumAdd(a, b);
        System.out.println("sum = " + sum);
    }

在这里插入图片描述

方法的参数叫做形参,main方法的参数叫实参,形参相当于实参的一份拷贝,这种传参方式被称为 按值传递(传值)
由此引申出一个知识点, 在Java中 是没有 传址 的概念,只有传值,所以我们在调用方法的时候,只需要注重 形参 和 实参 的类型 和 个数 是否匹配(相同)
在这里插入图片描述

1.1.2、既然讲到函数(方法),也就会涉及函数栈帧问题

想了解 c方面的或者想对比一下的,可以看这篇文章函数栈帧销毁与创建(vs2013)- 修改版
在这里插入图片描述

1.1.3、注意事项

  1. public 和 static 两个关键字在此处具有特定含义, 我们暂时不讨论, 后面会详细介绍.
  2. 方法定义时, 参数可以没有. 每个参数要指定类型
  3. 方法定义时, 返回值也可以没有, 如果没有返回值, 则返回值类型应写成 void
  4. 方法定义时的参数称为 “形参”, 方法调用时的参数称为 “实参”.
  5. 方法的定义必须在类之中, 代码书写在调用位置的上方或者下方均可.
  6. Java 中没有 “函数声明” 这样的概念

1.1.4、方法调用的执行过程

基本规则

定义方法的时候, 不会执行方法的代码. 只有调用的时候才会执行.
当方法被调用的时候, 会将实参赋值给形参.
参数传递完毕后,就会执行到方法体代码.
当方法执行完毕之后(遇到 return 语句), 就执行完毕, 回到方法调用位置继续往下执行
一个方法可以被多次调用.

1.1.4、实参和形参的关系(重要)

public static void main(String[] args) {
        int a = 10;
        int b = 20;
        System.out.println("交换前:" + "a = " + a + " b = " + b);
        swap(a, b);
        System.out.println("交换前:" + "a = " + a + " b = " + b);
    }

    public static void swap(int x, int y) {
        int tmp = x;
        x = y;
        y = tmp;
    }

在这里插入图片描述
原因分析:
刚才的代码, 没有完成数据的交换.
对于基础类型来说, 形参相当于实参的拷贝. 即 传值调用
可以看到, 对 x 和 y 的修改, 不影响 a 和 b
解决办法: 传引用类型参数 (例如数组来解决这个问题),这个数组 的 时候在讲。

1.2、没有返回值的方法

就像上面的swap函数,是没有返回值的

//有两种形式:
	public static void swap(int x, int y) {
        int tmp = x;
        x = y;
        y = tmp;
    }
    
    public static void fun(int c){
        return;
    }

在这里插入图片描述

1.3、方法的重载overlord(重点)

有些时候我们需要用一个函数同时兼容多种参数的情况, 我们就可以使用到方法重载

错误的例子

	public static void main(String[] args) {
        int a = 10;
        int b = 20;
        int ret = add(a, b);
        System.out.println("ret = " + ret);
        double a2 = 12.5;
        double b2 = 18.5;
        double ret2 = add(a2, b2);//图 13
        System.out.println("ret2 = " + ret2);
    }
    
    public  static  int add(int x,int y){
        return  x+y;
    }

在这里插入图片描述
由于参数类型不匹配, 所以不能直接使用现有的 add 方法

那么是不是应该创建这样的代码呢?

public static void main(String[] args) {
        int a = 10;
        int b = 20;
        int ret = addInt(a, b);
        System.out.println("ret = " + ret);
        double a2 = 10.5;
        double b2 = 20.5;
        double ret2 = addDouble(a2, b2);
        System.out.println("ret2 = " + ret2);
    }
    public static int addInt(int x, int y) {
        return x + y;
    }
    public static double addDouble(double x, double y) {
        return x + y;
    }

如果要计算float类型,那是不是要写一个addFloat函数,那这样不就很麻烦吗
所以就要使用方法的重载

1.3.1、使用重载

	public static void main(String[] args) {
        int a = 10;
        int b = 20;
        int ret = add(a, b);
        System.out.println("ret = " + ret);
        double a2 = 10.5;
        double b2 = 20.5;
        double ret2 = add(a2, b2);
        System.out.println("ret2 = " + ret2);
        double a3 = 10.5;
        double b3 = 10.5;
        double c3 = 20.5;
        double ret3 = add(a3, b3, c3);
        System.out.println("ret3 = " + ret3);
    }

    public static int add(int x, int y) {
        return x + y;
    }
    public static double add(double x, double y) {
        return x + y;
    }
    public static double add(double x, double y, double z) {
        return x + y + z;
    }

在这里插入图片描述

方法的名字都叫 add. 但是有的 add 是计算 int 相加, 有的是 double 相加; 有的计算两个数字相加,
有的是计算三个数字相加. 同一个方法名字, 提供不同版本的实现, 称为 方法重载

1.3.2、重载的规则

参考JavaSE的标准文档
可以不是用一个类,继承关系也是可以的

  • 方法名相同
  • 方法的参数不同(参数个数或者参数类型)
  • 方法的返回值类型不影响重载
    在这里插入图片描述

1.4、方法递归

1.4.1、递归的概念

一个方法在执行过程中调用自身, 就称为 “递归”.
递归相当于数学上的 “数学归纳法”, 有一个起始条件, 然后有一个递推公式
递推公式是递归的重点,推出它,递归就很好写。

使用递归之前,需要一个前提
  1. 有一个趋近于终止的条件(停止递归的条件)
  2. 自己调用自己

    public static void main(String[] args) {
        func();
    }
    
     这样写,就不满足 使用递归所需的第一个条件 没有一个终止递归的条件
     所以该程序会无限递归死循环,最终导致栈溢出(栈空间不是无限大,是有限,func方法一直调用自己下去,最终肯定是会 爆满/溢出 的)
    因为 每次调用 func方法时,都会为其在栈上空间开辟块自己的空间
    public  static void func(){
        func();
    }

在这里插入图片描述

那我该怎么去写一个可以使用的递归呢?

1. 有一个趋近于终止的条件(停止递归的条件)
2. 自己调用自己

代码示例: 递归求 N 的阶乘

	public static void main(String[] args) {
        //递归求 N 的阶乘
        int n = 5;
        int ret = fun(n);
        System.out.println(ret);
    }

    public static int fun(int n){
        if(n == 1){
            return 1;
        }
        return n * fun(n-1);
    }

  	 1! == 1 //这就是我们的起始条件,也是我们的终止条件
	 2! == 2*1 == 2 * 1!
	 3! == 3*2*1 == 3 * 2!
	 4! == 4*3*2*1 == 4 * 3!
	 5! == 5*4*3*2*1 == 5 * 4!
	 你发现了 求 5!的值,它是 5 *5-1)!
	 而  4== 4 * (4-1)3!  == 3 * (3-1)!
	    2!  == 2 *2-1)!
	
	 5! == 5 * 4!== 5 * 4 * 3! == 5 * 4 * 3 * 2! == 5 * 3 * 2 * 1
	 程序运行 跟我们刚才藏宝殿是一样的,一层一层的抢。从最里面的开始抢
	 也就从我们终止条件开始
	   n == 1;  return 1;// 这里的返回值 是返回到 调用它的上一层级(藏宝殿核心是第一层吗,抢完了,肯定去抢第二程啊)
	   n == 2   return 2* factorial(2-1) == 2 * 1 == 2
	   n == 3;  return 3 * 2 == 6
	   n == 4;  return 4 * 6 == 24
	   n == 5;  return 5 *   ==
	 考验你们的时候,在下面评论,看你们到底有没有看懂学会
	
	递归的字面意思
	    递归 n * factorial(n-1)l  n-1 就是它传过去的值,称为递, factorial(n-1)返回的值,称为归
	    结合称为: 递归。

在这里插入图片描述

执行过程
![public static void main(String[] args) {
        //递归求 N 的阶乘
        int n = 5;
        int ret = fun(n);
        System.out.println(ret);
    }

    public static int fun(int n){
        if(n == 1){
            return 1;
        }
        return n * fun(n-1);
    }

在这里插入图片描述

关于 “调用栈”
方法调用的时候, 会有一个 “栈” 这样的内存空间描述当前的调用关系. 称为调用栈.
每一次的方法调用就称为一个 “栈帧”, 每个栈帧中包含了这次调用的参数是哪些, 返回到哪里继续执行等信息.
后面我们借助 IDEA 很容易看到调用栈的内容

1.4.2、 递归练习

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

public static void main(String[] args) {
        //按顺序打印一个数字的每一位(例如 1234 打印出 1 2 3 4)
        int n = 4569;
        print(n);
    }

    public static void print(int n){
        if(n > 9){
            print(n / 10);
        }
        System.out.println(n % 10);
    }

在这里插入图片描述

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

public static void main(String[] args) {
        //递归求 1 + 2 + 3 + ... + 10
        int a = 10;
        int ret = sumAdd(a);
        System.out.println(ret);
    }

    public static int sumAdd(int n){
        if(n == 1){
            return 1;
        }
        return n + sumAdd(n - 1);
    }

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

public static void main(String[] args) {
        //代码示例3 写一个递归方法,输入一个非负整数,返回组成它的数字之和.
        // 例如,输入 1729, 则应该返回1+7+2+9,它的和是19
        int a = 1729;
        int ret = printAdd(a);
        System.out.println(ret);
    }
    public static int printAdd(int num){
        if(num <= 9){
            return num;
        }
        return num % 10 + printAdd(num / 10);
    }

代码示例4 求斐波那契数列的第 N 项

斐波那契数列介绍
斐波那契数列:1,1,2,3,5,8,13,21,34,55,89…

public static void main(String[] args) {
        ///代码示例4 求斐波那契数列的第 N 项
        //斐波那契数列:1,1,2,3,5,8,13,21,34,55,89...
        int n = 10;
        int ret = fibonacci(n);
        System.out.println(ret);
    }

    public static int fibonacci(int n){
        if(n == 1 || n == 2){
            return 1;
        }
        return fibonacci(n - 1) + fibonacci(n - 2);
    }

用 递归的方法来求 斐波那契数,效率很低

当我们求 fibonacci(40) 的时候发现, 程序执行速度极慢. 原因是进行了大量的重复运算

public static int cont = 0;

    public static void main(String[] args) {
        ///代码示例4 求斐波那契数列的第 N 项
        //斐波那契数列:1,1,2,3,5,8,13,21,34,55,89...
        int n = 40;
        int ret = fibonacci(n);
        System.out.println(ret);
        System.out.println("函数执行了:" + cont + "次");
    }

    public static int fibonacci(int n){
        if(n == 1 || n == 2){
            return 1;
        }
        if(n == 3){
            cont++;
        }
        return fibonacci(n - 1) + fibonacci(n - 2);
    }

在这里插入图片描述
在这里插入图片描述
可以使用迭代/循环的方式来求斐波那契数列问题, 避免出现冗余运算

    public static int cont = 0;

    public static int fibonacci(int n){
        int last2 = 1;
        int last1 = 1;
        int cur = 0;
        for (int i = 3; i <= n; i++) {
            cur = last1 + last2;
            last2 = last1;
            last1 = cur;
            cont++;
        }
        System.out.println("函数执行了:" + cont + "次");
        return cur;
    }

    public static void main(String[] args) {
        ///代码示例4 求斐波那契数列的第 N 项
        //斐波那契数列:1,1,2,3,5,8,13,21,34,55,89...
        int n = 40;
        int ret = fibonacci(n);
        System.out.println(ret);
    }

在这里插入图片描述

递归小结

递归是一种重要的编程解决问题的方式.
有些问题天然就是使用递归方式定义的(例如斐波那契数列, 二叉树等), 此时使用递归来解就很容易.
有些问题使用递归和使用非递归(循环)都可以解决. 那么此时更推荐使用循环, 相比于递归, 非递归程序更加高效

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/44134.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

04_SpringBoot整合Mybatis

文章目录SpringBoot整合Mybatis0x01_创建项目导入依赖0x02_编写配置文件0x03_编写功能代码SpringBoot整合Mybatis 欢迎关注公众号“小东方不败” 0x01_创建项目导入依赖 创建项目&#xff1a; 目前稳定的最新版本是2.7.5,勾选两个依赖&#xff1a;Lombok和Spring Web 然后需…

Nodejs -- Express 路由原理及设置模块化路由

文章目录1. 路由的概念1.1 什么是路由1.2 显示生活中的路由1.3 Express中的路由1.4 Express中路由的例子1.5 路由的匹配过程2 路由的使用2.1 最简单的用法2.2 模块化路由2.3 为路由模块添加统一前缀1. 路由的概念 1.1 什么是路由 广义上来讲&#xff0c;路由就是映射关系 1.…

yarn : 无法加载文件 C:\Users\sunlight\AppData\Roaming\npm\yarn.ps1,因为在此系统上禁止运行脚本。

问题&#xff1a; yarn安装好了&#xff0c;vscode报错 报错问题&#xff1a;yarn 无法加载文件 C:\Users\sunlight\AppData\Roaming\npm\yarn.ps1&#xff0c;因为在此系统上禁止运行脚本。 具体问题&#xff1a;cmd&#xff08;管理员运行&#xff09;中安装好了yarn &…

Angular使用管道和指令进行多语言切换

工作中经常遇到需要进行多种语言切换的项目。本文记录了一种在Angular页面中通过使用管道和自定义指令实现的语言切换方案。 1、实现效果 页面显示文字根据选择的语言自动进行翻译切换&#xff0c;如下图所示&#xff1a; 此时&#xff0c;页面模板的字符串全部按照管道格式书…

2023年IB生物有什么变化?

今天我们详细了解下2023年IBDP生物新课程内容、考试评估、内容、技能发展、科学本质等详细内容。IBDP生物新课程概述 IBDP新生物课程将于2023年2月开课&#xff0c;2023年8月首次授课&#xff0c;2025年5月进行首次考试。新课程反映社会变革&#xff0c;更加关注技能和概念、背…

【iMessage苹果推群发】苹果相册推archive到appstore开发证书(Development certificate)

推荐内容IMESSGAE相关 作者推荐内容iMessage苹果推软件 *** 点击即可查看作者要求内容信息作者推荐内容1.家庭推内容 *** 点击即可查看作者要求内容信息作者推荐内容2.相册推 *** 点击即可查看作者要求内容信息作者推荐内容3.日历推 *** 点击即可查看作者要求内容信息作者推荐…

DCHP通讯协议

从通讯TCP/IP的构成传输&#xff0c;到IP地址的分类&#xff0c;再到局域网与广域网的设置。 通讯协议的构成概述IPDHCP-设定动态IPDNS数据的流动广域网 网关局域网 交换机NAT桥接模式实操概述 前景知识&#xff1a;虚拟机与工艺库管理 扩展&#xff1a;NAT模式的实操。 1、T…

yolov5量化注意事项

&#xff08;1&#xff09;使用onnxsim 0.4.1版本、ort版本1.13.1 否则使用--dynamic True时所生成的onnx就会乱掉。 &#xff08;2&#xff09;利用trtexec生成engine 所使用的命令如下&#xff1a; trtexec.exe --onnxyolov5n_ptq_detect_dynamic.onnx --saveEngineptq_int…

小白学流程引擎-FLowable(二) — 从零搭建自己的FLowable服务 — 搭建流程服务-FLowable的新手指南

一、介绍 纵览Gitee搜索Flowable开源项目&#xff0c;大多都是已开发好的项目&#xff0c;而笔者从零开始搭建属于自己的Flowable引擎&#xff0c;并且是可以拿到生产上使用的。 二、软件架构 Springboot Flowable modeler idm Mysql SrpingBoot version&#xff1a;2.7…

牛客网verilog刷题知识点盘点(75道题的版本)

牛客网verilog刷题知识点盘点(75道题的版本) 还有几个坑没填 任务和函数 1.任务和函数必须在模块内定义&#xff0c;其作用范围仅适用于该模块&#xff0c;可以在模块内多次调用。 2.任务和函数中可以声明局部变量&#xff0c;如寄存器&#xff0c;时间&#xff0c;整数&…

企业云工如何高效居家协同办公?试试这个方法

近日的疫情反扑让全国各地的防疫压力增加&#xff0c;并且甚至很多地方不知道的啥时候就要被居家隔离&#xff0c;所以在新的防疫背景下&#xff0c;居家就顺理成章地成为一种常态化的学习和工作方式。 现在越来越多公司也将日常业务搬到了线上&#xff0c;以保证疫情期间公司的…

基于ssm的旅游网站的设计与实现

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…

vue——路由

目录 一、介绍路由 1、路由是什么 Vue Router 是 Vue.js 的官方路由。它与 Vue.js 核心深度集成&#xff0c;让用 Vue.js 构建单页应用变得轻而易举。 2、为什么要使用路由 3、主要用途 二、安装路由 1、安装命令 2、配置文件 3、在main.js 中进行挂载 三、案例展示 …

Linux服务器配置与管理(基于Centos7.2)任务目标(五)

文章目录一、知识目标二、能力目标二、任务实施任务一&#xff1a;安装Apache任务二&#xff1a;配置简单Web站点任务三&#xff1a;配置基于主机名的虚抛主机任务四&#xff1a;安装vsftpd任务五&#xff1a;匿名用户访问FTP服务器任务六&#xff1a;本地用户配置一、知识目标…

HummerRisk 使用场景-混合云安全治理(2)--阿里云安全最佳实践

背景&#xff1a; 阿里云安全最佳实践&#xff0c;是基于众多客户上云的成功案例萃取而成的最优化企业上云指导。每个最佳实践包括使用场景、多产品部署架构及部署手册。 最佳实践目前覆盖23种常用场景&#xff0c;目前有200篇最佳实践&#xff0c;涉及100款以上阿里云产品的…

20221128-1Spring_day02(资料来自黑马程序)

Spring_day02 今日目标 掌握IOC/DI配置管理第三方bean掌握IOC/DI的注解开发掌握IOC/DI注解管理第三方bean完成Spring与Mybatis及Junit的整合开发 1&#xff0c;IOC/DI配置管理第三方bean 前面所讲的知识点都是基于我们自己写的类&#xff0c;现在如果有需求让我们去管理第三方…

安卓讲课笔记5.11 菜单

文章目录零、本讲学习目标一、导入新课二、新课讲解&#xff08;一&#xff09;菜单概述1、选项菜单2、上下文菜单3、子菜单&#xff08;二&#xff09;选项菜单案例演示1、创建安卓应用2、准备图片素材3、字符串资源文件4 、主布局资源文件5、主界面类实现功能6、启动应用&…

2. Vue3 Composition API

Composition API 1.Composition API 接下来我们来介绍一下Vue3中新增的Composition API如何使用。注意Composition API仅仅是Vue3中新增的API&#xff0c;我们依然可以使用Options API。先来实现一下之前演示的获取鼠标位置的案例。做这个案例之前&#xff0c;需要先介绍一下…

MybatisPlus简单使用与自定义sql以及通过自定义sql实现多表联查的分页查询

MybatisPlus简单使用与自定义sql以及通过自定义sql实现多表联查的分页查询前言1. mybatis的简单使用2. MybatisPlus 的简单使用2.1 入门2.1.1 简单配置2.1.2 入门例子2.1.3 测试2.2 MybatisPlus自带封装的增删改查2.2.1 傻瓜式使用2.2.2 批量添加数据3 MybatisPlus 动态查询sql…

计算机网络---数据链路层扩展的以太网

&#xff08;一&#xff09;在物理层扩展以太网 使用光纤扩展&#xff1a;主机使用光纤和一对光纤调制解调器连接到集线器 使用集线器扩展&#xff1a;主机使用光纤和一对光纤调制解调器连接到集线器 使用集线器扩展的优缺点 优点 &#xff1a;使原来属于不同碰撞域&#xff0…