方法(函数)
方法的定义
概念:实现特定功能的一段代码,可重复使用(单一职能原则)
驼峰命名法 首字母小写,多个单词后面每个单词首字母大写
定义语法:
public static void 方法名称(){//遵循标识符命名规范
//方法主体 功能代码
}
经验:将需要在多个位置重复使用的一组代码,定义在方法内部
package com.zcs.lession06.demo2;
public class Demo7 {
public static void main(String[] args) {
// TODO Auto-generated method stub
}
/**
* 单一职能原则
* */
public static void show() {
System.out.println("展示数据");
}
public static void add() {
System.out.println("新增数据");
}
}
定义的位置
方法定义在类的内部,与main方法并列
public class Test1{
//可定义方法
public static void main(String[] args){
}
//可定义方法
}
方法的调用
package com.zcs.lession06.demo2;
public class Demo1 {
// JVM调用主方法
public static void main(String[] args) {
System.out.println("床前明月光");
//方法调用,使用方法名();
show2(9);//num=99;
System.out.println("疑是地上霜");
show2(5);
System.out.println("举头望明月");
show2(2);
System.out.println("低头思故乡");
show2(14);
}
/**
* 方法的编写的位置,在类的内部,方法的外部,跟main方法同级的
*
*/
public static void show1() {
for (int i = 0; i < 10; i++) {
System.out.print("-");
}
System.out.println();
}
/**
* 让用户自己定义要输出多少个-
*/
public static void show2(int num) {
for (int i = 0; i < num; i++) {
System.out.print("-");
}
System.out.println();
}
}
注意:调用方法时,会优先执行方法内部代码,结束后,返回到方法调用处,继续向下执行
方法的参数
多数情况下,方法与调用者之间需要数据的交互;调用者必须提供必要的数据,才能使方法完成相应的功能
调用方法时,所传入的数据被称为"参数"。
形参与实参
定义语法:
public static void 方法名称(形式参数){ //"形参"等价于"局部变量的声明"
//方法主体
}
调用语法:
方法名称(实际参数)//"实参"等价于"局部变量的赋值"
作用:方法的参数可以让代码功能更灵活、普适性更高、易于修改及维修
单个参数
public class Test3{
public static void main(String[] args){
System.out.println("床前明月光");
//实际参数:10
//调用带参方法时,必须传入实际参数,为形式参数赋值
printSign(10);
System.out.println("疑是地上霜");
System.out.println("举头望明月");
System.out.println("低头思故乡");
}
//形式参数:int count 当方法被执行时,循环count次
public static void printSign(int count){
for(int i = 1; i <= count; i++){
System.out.print("-");
}
System.out.println();
}
}
package com.zcs.lession06.demo2;
public class Demo2 {
public static void main(String[] args) {
//调用时根据形参的数据类型给值
//可以适用于自动类型转换
//也可以适用于自动类型提升
/*
* 两种数据类型之间相互兼容
* 目标类型大于源类型
* */
show3(1+"");
String hello = "hello world";
//和形参的名称没有任何关系,只需求数据类型一致
show3(hello);
System.out.println("程序结束");
}
public static void show3(String word) {
System.out.println(word);
}
public static void show2(double num) {
System.out.println("22222");
System.out.println(num);
}
/**
* num 形参设置数据类型为int,
* */
public static void show(int num) {
System.out.println(num);
}
}
多个参数
public class Test4{ public static void main(String[] args){ System.out.println("床前明月光"); //实际参数:10 /* *调用带参方法时,必须传入实际参数, *类型、个数、顺序、必须与形参对应 */ printSign(10,'#'); System.out.println("疑是地上霜"); System.out.println("举头望明月"); System.out.println("低头思故乡"); } /* *形式参数:int count char sign *当方法被执行时,打印count次sign */ public static void printSign(int count,char sign){ for(int i = 1; i <= count; i++){ System.out.print(sign); } System.out.println(); }}
package com.zcs.lession06.demo2;public class Demo3 { public static void main(String[] args) { System.out.println("床前明月光"); show(10,"*"); System.out.println("疑是地上霜"); show(5,"@"); System.out.println("举头望明月"); show(20,">"); System.out.println("低头思故乡"); //实参必须按照形参的参数列表 } /** * 参数列表: * 参数的个数 * 参数的类型 * 参数的顺序 * */ public static void show(int num, String sign) { for (int i = 0; i < num; i++) { System.out.print(sign); } System.out.println(); }}
package com.zcs.lession06.demo2;import java.util.Scanner;public class Demo4 { public static void main(String[] args) { double sum1 = add(10, 10); double sum2 = muit(10, 10); double sum3 = div(10, 10); double sum4 = sub(10, 10); System.out.println(sum1); System.out.println(sum2); System.out.println(sum3); System.out.println(sum4); Scanner input = new Scanner(System.in); System.out.println("请输入第一个操作数:"); int num1 = input.nextInt(); System.out.println("请输入运算符:"); String sgin = input.next(); System.out.println("请输入第一个操作数:"); int num2 = input.nextInt(); calculator(num1, num2, sgin); } public static double add(double num1, double num2) { System.out.println(num1 + " + " + num2 + " = " + (num1 + num2)); return num1 + num2; } public static double muit(double num1, double num2) { System.out.println(num1 + " * " + num2 + " = " + (num1 * num2)); return num1 * num2; } public static double div(double num1, double num2) { System.out.println(num1 + " / " + num2 + " = " + (num1 / num2)); return num1 / num2; } public static double sub(double num1, double num2) { System.out.println(num1 + " - " + num2 + " = " + (num1 - num2)); return num1 - num2; } public static void calculator(double num1, double num2, String sgin) { if (sgin.equals("+")) { System.out.println(num1 + " + " + num2 + " = " + (num1 + num2)); } else if (sgin.equals("-")) { System.out.println(num1 + " - " + num2 + " = " + (num1 - num2)); } else if (sgin.equals("*")) { System.out.println(num1 + " * " + num2 + " = " + (num1 * num2)); } else if (sgin.equals("/")) { System.out.println(num1 + " / " + num2 + " = " + (num1 / num2)); } else { System.out.println("你输入的运算符有误"); } }}
package com.zcs.lession06.demo2;import java.util.Scanner;public class Demo5 { public static void main(String[] args) { // null 代表空 内存空间为空 // NullPointerException String a = null; System.out.println(a.equals("哈哈")); Scanner input = null; input.next(); System.out.println(a); } public static String login(String username) { if (username.equals("admin")) { return "ok"; } else { return "no"; } } public static Scanner getScanner() { Scanner input = new Scanner(System.in); return null; } public static String gerWord() { return "hello 哈"; } public static int show() { return (int) 0.0; }}
如何定义参数
禁言:根据具体的业务需求,来定义方法的参数
返回值与返回值类型
概念:方法执行后的返回结果
方法执行后,一些情况下无需返回结果;另一些情况下则必须返回结果
例如:存款操作无需返回结果,取款操作必须返回结果
定义的语法:
//规定返回值的具体类型(基本、引用、void)public static 返回值类型 方法名称(形式参数列表){ //方法主体 return value;//返回值 //根据需求返回一个结果(值)}
package com.zcs.lession06.demo2;public class Demo6 { public static void main(String[] args) { add(1, 1); } public static void show() { if(true) { return; } } public static String getDays(int chose) { if(chose==1) { return "星期一"; }else if(chose==2) { return "星期二"; }else if(chose==3) { return "星期三"; }else { System.out.println("没有这个选择"); } return ""; } public static String getDays2(int chose) { switch(chose) { case 1: return "1"; default: return "2"; } } public static int add(int num1, int num2) { if (true) { System.out.println("xx"); // 1、值返回出去 // 2、结束方法 return num1 + num2; } System.out.println("xxxx"); return 0; }}
调用语法:
变量=方法名称();//变量类型与返回值一致
需求:定义方法、计算两个整数的和,并返回结果,在main中打印
public class Test5{ public static void main(String[] args){ /* *接收返回值:方法调用的表达式 *最终即代表了所返回的结果 */ int result = add(5,6); System.out.println(result); } //返回值类型:定义时,即约定了返回值的结果类型 public static int add(int a , int b){ //返回值:与返回值类型匹配的具体结果,在return关键字的后面追加具体值 return a + b; }}
return关键字
public class Test6{ public static void main(String[] args){ System.out.println("两值的和:"+calc(5,2)); System.out.println("两值的差:"+calc(5,2)); } public static int calc(int a , int b){ return a + b; return a - b;//报错:一个方法只能有一个返回值 }}
public class Test7{ public static void main(String[] args){ String result = isEven(10); System.out.println(result); } public static String isEven(int num){ if(num%2 == 0){ return "偶数"; }else{ return "奇数"; } }}
return的两种用法:
1、应用在具有返回值类型的方法中:
return value;//表示结束当前方法,并伴有返回值,返回方法调用处
2、应用在没有返回值类型(void)的方法中:
return;//表示结束当前方法,直接回到方法调用处
public static void show(){ for(int i = 1; i<=100; i++){ return;//结束当前方法直接返回 }}
小结
注意:一个类中可以定义多个方法,方法之间属于并列关系,不可嵌套
经验:一个方法只做一件事
好处:
- 减少代码冗余
- 提高复用性
- 提高可读性
- 提高可维护性
- 方便分工合作
多级调用
public class Test1{ public static void main(String[] args){ m1(); public static void m1(){ System.out.println("m1() - start"); m2(); System.out.println("m1() - end"); } public static void m2(){ System.out.println("m1() - start"); System.out.println("m1() - end"); } }}
优先执行方法内部代码,结束后,返回到调用处,继续向下执行
无穷递归
public class Test2{ public static void main(String[] args){ m1(); } public static void m1(){ System.out.println("m1() - start"); m1();//当方法自己调用自己时,如果没有正确的出口条件,则产生无穷递归 System.out.println("m1() - end"); }}
java.lang.StackOverflowError 内存溢出
递归
什么是递归
解决具有既定规律的问题时,在方法内部再次调用自己方法的一种编程方式
何时使用递归
当需要解决的问题可以拆分若干个小问题,大小问题的解决方式相同,方法中自己调用自己
使用循环解决的常规问题,都可以替换成递归解决
如果正确使用递归
设置有效的出口条件,可以让调用链上的每个方法都可以正确放回,避免无穷递归
循环阶乘
//计算5的阶乘:5!=5*4*3*2*1 ;public class Test3{ public static void main(String[] args){ System.out.println(factorial(5)); } public static int factorial(int n){ int sum = 1; for(int i = 2;i <= n; i++){ sum *= i; //循环计算阶乘较为简单 依次与每个值相乘即可 } return sum; }}
递归阶乘
阶乘的定义: n!=n*(n-1)*(n-2)*(n-3)....
递进:每一次推进,计算都比上一次变得简单,直至简单到无需继续推进,就能获得结果。也叫达到出口
回归:基于出口的结果,逐层向上回归,依次计算每一层的结果,直至回归到最顶层
public class Test4{ public static void main(String[] args){ System.out.println(getFive(5)); } //多个方法解决问题的思路相同,同时遵循着相同的规律。如何整合为一个方法? public static int getFive(int n){ //n=5 return n * getFour(n-1);//5 * 4 } public static int getFour(int n){ //n=4 return n * getThree(n-1);//4 * 3 } public static int getThree(int n){ //n=3 return n * getTwo(n-1);//3 * 2 } public static int getTwo(int n){ //n=2 return n * getOne(n-1);//2 * 1 } public static int getOne(int n){ //n=1 return 1; //1!=1 } }
递归阶乘
public class Test5{ public static void main(String[] args){ System.out.println(factorial(5)); } public static int factorial(int n){ /* *当拿n=1时,并没有计算出1!=1而是继续递进,计算1!=1*0!, *所以导致永远没有出口条件,则造成无穷递归,内存溢出! */ return n * factorial(n-1); }}
java.lang.StackOverflowError 内存溢出
递归阶乘
public class Test6{ public static void main(String[] args){ System.out.println(factorial(5)); } public static int factorial(int n){ //增加出口条件,n=1时,无需计算阶乘,直接返回结果1 if(n == 1){ return 1; } return n * factorial(n-1); }}
注意:所以能以递归解决的问题,循环都可以解决。当解决复杂问题时,递归的实现方式更为简单
课堂案例
//使用递归完成斐波那契数列package Test06;import java.util.Scanner;public class Test1{ public static void main(String[] args){ Scanner input = new Scanner(System.in); System.out.println("请输入你要计算第几项斐波那契数列"); int num = input.nextInt(); System.out.println(fibonacci(num)); } public static int fibonacci(int n) { if(n == 0){ return 0; }else if(n == 1) { return 1; } return fibonacci(n-1) + fibonacci(n-2); }}
总结
-
方法的概念:
实现特定功能的一段代码,可反复使用
-
方法的组成:
public static 返回值类型 方法名(形参列表…){
//方法主体
[returm 返回值]
}
-
方法调用
方法名(实参列表…)
-
方法的好处
减少冗余、提高复用性、可读性、可维护性、方便分工合作
-
递归
将大问题拆分成若干个小问题,大小问题的解决方法相同,有固定规律,需设置有效的出口条件,方法中自己调自己