作者:韩茹
公司:程序咖(北京)科技有限公司
程序咖:IT职业技能评测平台
网址:https://www.chengxuka.com
任务
1.方法 2.方法的重载 3.递归
Java的方法类似于其它语言的函数,是一段用来完成特定功能的代码片段。 方法的本质,就是一段代码。实现某个独立的功能。可以被多次调用。
DRY(Don't Repeat Yourself)原则,把能被复用的逻辑抽取出来 实现相对独立的逻辑 实现比较复杂的逻辑 可以对具体实现进行隐藏/封装
简化代码,提高代码的可读性,提高代码的可维护性【版本迭代】
需要以下两个步骤,缺一不可:
语法: 访问权限修饰符 其他修饰符 返回值类型 函数名称(参数列表) { //函数体【方法体】 return 返回值; } 示例: public static void getSum(){ 方法体; }
踩坑:方法声明的位置。
示例代码:
/* * 方法 */ public class Demo36Method { /** * main函数,不同于其他方法,是一个程序的唯一的入口。JVM自动执行main()方法中的内容。 * * @param args */ public static void main(String[] args) { //1.此处求1-10的和 //step2:调用方法:方法名() getSum();//方法的调用处 System.out.println("其他的代码。。。。10行。。。"); //2.此处求1-10的和 getSum(); System.out.println("Hello world。。。"); //3.求1-10的和 getSum(); } //step1:定义一个方法,也叫方法的声明 /* * (),方法的标志 * [],数组 * <>,泛型 * {},一段代码,一个类,一个方法,一个代码块 * * 方法名:小驼峰命名方式 * 注意点:方法声明的时候,方法里的代码不会被执行的。 */ public static void getSum(){ int sum = 0; for(int i = 1;i<=10;i++){ sum += i; } System.out.println("1-10的和:"+sum); } }
运行结果:
课堂画图:
示例代码:
public class Demo37Method { public static void getSum(){ //求1-100的和 int sum = 0; for(int i = 1;i <= 100;i++){ sum += i; } System.out.println(sum); } public void printTriangle(){ for(int i = 0;i<5;i++){ for(int j = 0;j <= i;j++){ System.out.print("*"); } System.out.println(); } } public static void main(String[] args) { System.out.println("Hello World!"); /* 练习1:声明一个方法:有static关键字。用于求1-100的和。将结果在方法中打印。主函数中调用该方法2次。 练习2:声明一个方法:没有static关键字。用于打印一个三角形。主函数中调用该方法3次。 */ getSum(); getSum(); Demo56 d = new Demo56(); d.printTriangle(); d.printTriangle(); d.printTriangle(); } }
方法的调用过程:
a.一个完整的函数包含声明部分和实现部分 b.访问权限修饰符:public,default【如果没有添加任何的访问权限修饰符,则默认为default,而default不需要显式的写出来】,目前使用的访问权限修饰符都和main函数保持一致,使用public c.其他修饰符:static 【静态的】,要么不写【非静态函数】,要么写上【静态函数】 d.返回值类型:函数运行之后所得到的结果的数据类型,如果没有运行结果,则直接为void【空】 e.函数名称:标识符【遵循小驼峰】,尽量做到顾名思义 f.参数列表:如果函数所实现的功能中有未知项参与运算,就可以将未知项设置为参数 实际参数:实参,在函数外面定义,表示实际参与运算的值或者变量,作用为了给形参进行赋值 形式参数:形参,在函数中定义,用于接收实参的值,相当于是一个未被赋值的变量 形参数据类型 形参变量名称 形参 = 实参; g.函数体:抽取出来的具有特殊功能的代码段 h.return 返回值:将当前函数运行之后的结果进行返回,返回给当前函数的调用者 return:结束整个方法
语法:函数名称(实参列表) 注意: a.实参的数量和类型必须和形参保持完全的一致,实现书写的顺序也必须和形参中的顺序保持完全一致 b.函数之间只能进行相互的调用,而不能在函数中声明函数,就目前而言声明的函数都和main函数时并列的 c.定义函数的时候,运算的结果会返回给调用者【在哪个函数中调用,运算的结果返回给哪个函数】
踩坑:方法中的注意点如下:
public class Demo38Method { public static void main(String[] args) { /* * 方法的注意点: * 1、方法只有声明,没有调用。那就白写了。 * 2、方法没有声明,直接调用。那么报错。该方法未定义。 * 3、方法的声明位置,类里,其他方法外。关键是在哪里调用。 * 4、同一个类中,方法名不能冲突。 * * 补充:局部变量,方法里声明的变量。在哪个方法中声明的变量,就只能在哪个方法中使用。作用域。 */ test2(); } public static void test1(){ System.out.println("test1()方法。。"); int num = 100; test2(); } public static void test2(){ System.out.println("test2()方法。。"); // System.out.println(num);//报错 test1(); } // public static void test2(){ // System.out.println("我是另一个方法。。。"); // } }
课堂练习1:声明方法
1. 最简单的方法 void sum(){ System.out.println("加法操作"); } 2. 拥有修饰符的方法 public static void sum(){ System.out.println("加法操作"); } 3. 拥有参数的方法 public static void sum(int a,int b){ System.out.pritln("两数相加结果"+a+b); } 4.拥有返回值的方法 public static int sum(int a,int b){ return a+b; }
课堂练习2:调用方法
public class Test { public static void main(String[] args) { //需求:打印多遍九九乘法表 /* for(int i = 1;i <= 9;i++) { for(int j= 1;j <= i;j++) { System.out.print(j + "x" + i + "=" + i * j + " "); } System.out.println(); } for(int i = 1;i <= 9;i++) { for(int j= 1;j <= i;j++) { System.out.print(j + "x" + i + "=" + i * j + " "); } System.out.println(); } */ System.out.println("start"); print(); print(); print(); print(); System.out.println("end"); } //对于打印九九乘法表的功能提取出来一个函数 /* 访问权限修饰符 其他修饰符 返回值类型 函数名称(参数列表) { //函数体【方法体】 return 返回值; } */ public static void print() { for(int i = 1;i <= 9;i++) { for(int j= 1;j <= i;j++) { System.out.print(j + "x" + i + "=" + i * j + " "); } System.out.println(); } } }
方法中的参数
工作原理:调用方法的时候,用实参给形参进行赋值,这个过程被称为传参
形参就是一个变量,实参就是一个常量或者携带着值的变量,传参就是把实参赋值给形参
传参时需要注意的事项:实参的数量和类型必须和形参的数量和类型保持一致【相兼容的数据类型】
示例代码:
//程序咖 public class Demo39Param { public static void main(String[] args) { /* * 参数: * 形式参数:简称形参。声明方法的时候,用于接收外部传入的数据。 * 实际参数:简称实参。调用方法的时候,传给形参的具体的赋值。 * * 方法调用:方法名,实参必须严格匹配形参。 * 方法名(实参); * * 将实参赋值给形参的过程:参数的传递。简称:传参。 */ // 1.求1-10的和 getSum(10);//实参 // 2.求1-20的和 getSum(20); //3.求1-100的和 getSum(100); } /** * 方法用于求1-n的和。 * 参数:声明方法的时候,如果有些变量的数值,无法确定。就可以定义为参数。写在()内。 * 数值由调用处传入。 * * 参数的本质:就是一个局部变量:声明和赋值分开了 * * @param n */ public static void getSum(int n) {//形参:用于接收外部传入的数据 int sum = 0; for (int i = 1; i <= n; i++) { sum += i; } System.out.println("1-"+n+"的和:" + sum); } }
执行过程分析:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2ooL6xzm-1622424085667)(https://img.chengxuka.com/ruby0014/3%E5%8F%82%E6%95%B0%E7%9A%84%E4%BC%A0%E9%80%92.png/mark)]
课堂练习:
//演示参数的使用 class Demo40 { public static void main(String[] args) { //需求:交换两个变量的值 //实参 int a = 10; int b = 20; //调用函数 swap(a,b); System.out.println("main函数中的a=" + a);//10 System.out.println("main函数中的b=" + b);//20 } //分析:需要参数(两个参数) // 不需要返回值 //形参:没有携带值的变量,多个变量之间使用逗号分隔 public static void swap(int a,int b) { //定义一个中间的临时变量 int temp = 0; temp = a; a = b; b = temp; System.out.println("swap函数中的a=" + a);//20 System.out.println("swap函数中的b=" + b);//10 } }
方法的返回值
return关键字的使用
a.表示一个函数执行完成之后所得到的结果
void:表示没有返回值 b.return的使用
1>在没有返回值的函数中使用return
return单独成立一条语句,类似于break或者continue,后面不能跟任何的数值
作用:结束整个方法 2>在一个有返回值的函数中使用return
这种情况下函数中必须出现return
return后面必须跟一个具体的数值,而且数值的类型和返回值类型必须保持一致
作用:结束整个方法,并且将返回值携带给调用者 3>如果一个自定义的函数有返回值,并且在方法中遇到了分支结构,使用return
在每一个分支后面都需要出现一个return
示例代码:
//程序咖 public class Demo41Return { public static void main(String[] args) { /* * 一个方法的返回值:一个方法执行之后的结果,返回给调用处。 * 声明方法的时候:标注清楚该方法的返回值类型,如果没有返回值就写void。 */ // 在main中获取1-10的和结果,放大10倍,打印 int res = getSum();//相当于int res = sum System.out.println(res * 10); } /** * 一个方法如果有返回值,那么声明的时候要写清楚返回值类型,只能写一个。 * 如果没有返回值,就写void * 方法中必须使用return语句返回这个结果。 * @return */ public static int getSum() {//This method must return a result of type int int sum = 0;// 局部变量,只能在该方法中使用 for (int i = 1; i <= 10; i++) { sum += i; } // System.out.println(sum);//55 return sum;//将sum的值,传递给方法的调用处 } }
分析执行过程:
踩坑:return的注意点:
return语句: 用法:1、将结果返回给调用处。2、结束该方法的执行。 注意点: 1、如果一个方法声明有返回值(不是void),那么方法中必须使用return语句,返回结果。 2、方法声明的返回值类型,和return语句后的数据类型一致。但是包含那些能够自动转型的类型 返回值类型int:int,byte,short,char 返回值类型double:byte,short,int,long,float,double 3、如果一个方法声明有返回值,方法中有分支语句,循环语句。。无论执行哪个分支,最终有return语句可以执行。 4、return用于返回结果,并强制结束该方法的执行。习惯上return语句往往是方法中的最后一行代码。 5、如果一个方法声明没有返回值类型,void,方法中
示例代码:
public class Demo42Return { public static void main(String[] args) { /* * return语句: * 用法:1、将结果返回给调用处。2、结束该方法的执行。 * * * 注意点: * 1、如果一个方法声明有返回值(不是void),那么方法中必须使用return语句,返回结果。 * * 2、方法声明的返回值类型,和return语句后的数据类型一致。但是包含那些能够自动转型的类型 * 返回值类型int:int,byte,short,char * 返回值类型double:byte,short,int,long,float,double * * 3、如果一个方法声明有返回值,方法中有分支语句,循环语句。。无论执行哪个分支,最终有return语句可以执行。 * * 4、return用于返回结果,并强制结束该方法的执行。习惯上return语句往往是方法中的最后一行代码。 * * 5、如果一个方法声明没有返回值类型,void,方法中 */ // System.out.println(test1()); // System.out.println(test5()); // // test6(); test7(); } public static int test1(){ return 200; } public static int test2(){ byte i = 100; return i; } public static int test3(){ int age = 30; if(age < 0){//if,switch,for,while,do-while return 0; }else{ return age; } } public static int test4(){ return 0;//返回结果,并结束该方法的执行。 // System.out.println("haha"); } public static int test5(){ int age = 10; if(age < 0){ return 0;//返回结果,结束方法 } System.out.println("...."+age); return age; } public static void test6(){ int age = -30; if( age < 0){ return ;//没有返回,只用于结束方法 } System.out.println("你的年龄:"+age); } public static void test7(){ for(int i=1;i<=10;i++){ if (i==5){ // break;//强制结束循环语句 return; } System.out.println(i); } System.out.println("test7..over..."); } }
方法的返回值练习
class Demo43 { public static void main(String[] args) { show(); } /* 1>在没有返回值的函数中使用return return单独成立一条语句,类似于break或者continue,后面不能跟任何的数值 作用:结束整个方法 */ public static void show() { System.out.println("Hello World!"); int x = 10; if(x > 5) { return;//在某些情况下,可以使用return替换break } // 错误: 无法访问的语句 System.out.println("Hello World!========"); } }
class Demo44 { public static void main(String[] args) { int result = add(10,20); System.out.println(result); System.out.println(add(11,22)); //如果一个函数返回值类型为void,则不能再调用函数的同时直接打印 // 错误: 此处不允许使用 '空' 类型 //System.out.println(show(11,22)); show(11,22); } /* 2>在一个有返回值的函数中使用return 这种情况下函数中必须出现return return后面必须跟一个具体的数值,而且数值的类型和返回值类型必须保持一致 作用:结束整个方法,并且将返回值携带给调用者 */ //需求:求两个变量的和 public static int add(int a,int b) { int sum = a + b; //谁调用,返回给谁 //return每次只能携带一个数据返回 return sum; } public static void show(int a,int b) { int sum = a + b; System.out.println(sum); } }
class Demo45 { public static void main(String[] args) { int result = compare(34,67); System.out.println(result); } /* 3>如果一个自定义的函数有返回值,并且在方法中遇到了分支结构,使用return 在每一个分支后面都需要出现一个return */ //需求:比较两个变量的大小,返回较大的一个 public static int compare(int num1,int num2) { //多分支 /* if(num1 > num2) { return num1; } else if(num1 < num2) { return num2; } else { return num1; } */ //出现的问题:在使用单分支的时候,分支内部有return,这时编译还是不通过 //解决办法:在单分支的外面再添加一个返回值,返回值随意,只要类型和返回值类型匹配就ok //单分支 if(num1 > num2) { return num1; } //没有实际意义,作用只是为了匹配语法 return 0; } }
方法重载的概念:
同一个类中,方法名字相同,参数列表不同。则是重载 注意: 1. 参数列表的不同包括,参数个数不同,参数数据类型不同,参数顺序不同 2. 方法的重载与方法的修饰符和返回值没有任何关系
方法的重载:
概念:一个类中的,一个功能方法的多种体现形式(有不同的方法体)。 举例: 1、人类,有吃的功能:eat() eat(食物); eat(药); eat(口香糖); 2、求和的功能: getSum(int i,int j); getSum(double d1, double d2); 3、水: 常温:液态 0度以下:固态 100度以上:气态 就是同一个功能的方法,因为参数的不同,调用的具体的方法也不同。 如何判定多个方法是否是重载的?衡量标准,要同时满足以下三条: A:必须同一个类中。 B:方法名称必须一致。 C:参数列表必须不同。(顺序,个数,类型) 和static,public,返回值,void等等都没有关系。 优点: 1、简化了开发的压力 2、简化了记忆的压力 3、调用方法更方便,更简洁,又满足了不同的情况 基本原理: 当方法名称一致时,通过形式参数列表的不同来选择要执行的方法。
示例代码:
//演示方法的重载 //测试类 public class Demo46Overload { public static void main(String[] args) { //对于重载函数而言,具体调用的是哪个函数,取决于所传的参数 Check.show("10"); Check.show("10",10); } } //实体类 /* 在同一个类中,如果满足以下的条件,则称为这几个方法之间彼此重载 a.方法名相同 b.参数不同【数量不同或者类型不同】 c.访问权限修饰符和返回值类型没有影响 */ class Check { public static void show() { System.out.println("无参无返回值的show"); } //1.改变参数 public static void show(int a) { System.out.println("int的show"); } public static void show(String a) { System.out.println("String的show"); } public static void show(String a,int b) { System.out.println("String int的show"); } //2.改变返回值:返回值对方法的重载没有任何影响 //只改变返回值类型,其他都不改变,则对于编译器而言,则认为是同一个方法 /* public static String show() { System.out.println("String返回值的show"); return "abc"; } */ //3.访问权限修饰符 //只改变访问权限修饰符,其他都不改变,则对于编译器而言,则认为是同一个方法 /* static void show() { System.out.println("show"); } */ }
课堂画图:
递归算法的概念:在一个方法的方法体内调用该函数本身,称为函数的递归。
方法递归包含了一种隐式的循环,会重复执行某段代码,但是这种重复不需要使用循环语句来进行控制
示例代码:求和
public class Demo47Recursion { public static int getSum(int n){ if(n == 1){ return 1; } return getSum(n-1)+n; } public static void main(String[] args) { int sum = getSum(5); System.out.println(sum); } }
运行结果:
分析过程
示例代码:求斐波那契数列
class Demo48Fibonacci { public static void main(String[] args) { /* 斐波那契数列 1,2,3,4,5,6, 7, 8, 9,10,11,..... 1,1,2,3,5,8,13,21,34,55,89.... 分析: 1.第一个位置和第二个位置上的数是固定的,都是1 2.第n个位置上的数 = 第n - 1个位置上的数 + 第n - 2个位置上的数 fun(1) = 1 fun(2) = 1 fun(3) = fun(2) + fun(1) = 1 + 1 fun(4) = fun(3) + fun(2) = fun(2) + fun(1) +fun(2) fun(5) = fun(4) + fun(3) = fun(3) + fun(2) + fun(2) + fun(1) = fun(2) + fun(1) + fun(2) + fun(2) + fun(1) .... fun(n) = fun(n - 1) + fun(n -2) */ int result1 = fun(10); System.out.println(result1); } //需求:报个数,获取在斐波那契数列中对应的数 public static int fun(int n) { if(n == 1 || n == 2) { return 1; } else { int num1 = fun(n - 1); int num2 = fun(n -2); int sum = num1 + num2; System.out.println("num1=" + num1 + ",num2=" + num2); return sum; } } }
示例代码:求1~某个数之间所有整数的和
class Demo49 { public static void main(String[] args) { int result = total(100); System.out.println(result); } //需求:求1~某个数之间所有整数的和 //普通方式 public static int add(int n) { int sum = 0; for(int i = 1;i <= n;i++) { sum += i; } return sum; } //使用递归实现 /* total(1) = 1 total(2) = total(1) + 2 total(3) = total(2) + 3 = total(1) + 2 + 3 .... total(n) = total(n - 1) + n */ public static int total(int n) { if(n == 1) { return 1; } else { return total(n - 1) + n; } } }
课堂练习:
class Demo50 { public static void main(String[] args) { method1(); method2(10); } public static void method1() { //输出100~200之间能被3整除的数 for(int i = 100;i <= 200;i++) { if(i % 3 != 0) { continue; } System.out.println(i); } } public static void method2(int num) { //判断一个数是否为质数 //质数:除了1和本身能整除,如果出现一个数可以将这个数整除的话,那么这个数就不是质数 //1.假设是质数 boolean isPrime = true; //2.寻找能够整除num的数,只要出现一个,则原来的假设被推翻 for(int i = 2;i < num;i++) { //3.大对小求余 if(num % i == 0) { //4.修改原来假设的状态 isPrime = false; break; } } return isPrime; } }
课堂练习:
class Demo51 { public static void main(String[] args) { getNum(100); getNum1(10); exchange(); } //1.求1--某个数之间可以被7整除的数的个数 public static int getNum(int n) { int count = 0; for(int i = 1;i <= n;i++) { if(i % 7 == 0) { count++; } } return count; } //2.计算1到某个数以内能被7或者3整除但不能同时被这两者整除的数的个数。 public static int getNum1(int n) { //&& int count = 0; for(int i = 1;i <= n;i++) { if((i % 7 == 0 || i % 3 == 0) && i % 21 != 0) { count++; } } //嵌套if语句 int count1 = 0; for(int i = 1;i <= n;i++) { if(i % 7 == 0 || i % 3 == 0) { if(i % 21 != 0) { count1++; } } } return count; } //3.从键盘输入两个数,赋值给两个变量,交换这两个变量的值【三种方法】 public static void exchange() { int a = 10; int b = 20; //方式一:异或【面试题:不采用第三方变量,交换两个变量的值】 a = a ^ b; //10 ^ 20 b = a ^ b; //10 ^ 20 ^ 20 = 10 a = a ^ b; //10 ^ 20 ^ 10 = 20 //方式二:加法 int c = a + b;//30 a = c - a;//30 - 10 =20 b = c - a; //30 - 20 = 10 a = a + b; b = a - b;//10 a = a - b;//20 //方式三: int temp = a; a = b; b = temp; } }