1.方法是什么
方法是一种语法结构,它可以把一段代码封装成一个功能,以便重复调用。
示例代码如下:
publicstaticvoidmain(String[] args) { intc1=sum(10, 30); System.out.println(c1); } publicstaticintsum(inta, intb) { intc=a+b; returnc; }
2.方法的定义、调用
2.1完整格式的方法定义、调用
方法定义的完整格式:
修饰符 返回值类型 方法名(形参列表){
方法体代码(需要执行的功能代码);
return 返回值;
}
示例如下图所示。
方法必须调用才可以运行,调用格式:方法名(...);
方法申明了具体的返回值类型,内部必须使用return返回对应类型的数据。
形参列表可以没有或者有一个或多个,如果有多个形参,形参之间必须用”,”隔开,且不能初始化值。
2.2其他形式的方法定义、调用
方法定义时:返回值类型、形参列表可以按照需求进行填写。
示例代码如下:
publicstaticvoidmain(String[] args) { print();// HelloWorld// HelloWorld// HelloWorld } /*** create by: 全聚德在逃烤鸭、* description: 无参数无返回值的方法* create time: 2022/3/28 0028 10:03** @param* @return void*/publicstaticvoidprint() { for (inti=0; i<3; i++) { System.out.println("HelloWorld"); } }
如果方法不需要返回结果,返回值类型必须申明成void(无返回值),此时方法内部不可以使用return返回数据。
方法如果没有参数,或者返回值类型申明为void可以称为无参数、无返回值的方法,依次类推
3.方法使用的常见问题
1.方法的编写顺序无所谓。
方法定义在main方法上面或下面均可,二者没有区别。
示例代码如下:
//定义在main方法上面publicstaticintsum1(inta, intb) { returna+b; } publicstaticvoidmain(String[] args) { // 方法的编写顺序无所谓。System.out.println(sum1(10,20)); // 30System.out.println(sum2(100,200)); // 300 } //定义在main方法下面publicstaticintsum2(inta, intb) { returna+b; } 2.方法与方法之间是平级关系,不能嵌套定义。方法与方法之间不能嵌套,如果把某一方法定义到另一方法内部,会报错。示例代码如下:publicstaticvoidmain(String[] args) { publicstaticvoidprint() { // 报错,方法定义不能嵌套System.out.println("HelloWorld"); } }
3.方法的返回值类型为void(无返回值),方法内则不能使用return返回数据,如果方法的返回值类型写了具体类型,方法内部则必须使用return返回对应类型的数据。
示例代码如下:
publicstaticvoidprint() { System.out.println("HelloWorld"); // return 2; // 报错,无返回值方法中不能用return返回数据 } publicstaticintadd() { Stringa="A123"; intb=0; // 没有return,报错,必须有int型返回值// return "a"; // 报错,返回值类型必须与方法定义中的返回值类型一致,为int型returnb; }
4.return语句下面,不能编写代码,因为永远执行不到,属于无效的代码。
示例代码如下:
publicstaticintsum(inta, intb) { returna+b; // System.out.println("HelloWorld"); // 报错,上方有return语句,此行代码不会执行 }
5.方法不调用就不执行, 调用时必须严格匹配方法的参数情况。
方法定义后,在使用时必须调用,否则不会执行,且在调用过程中,传入参数的数量和类型必须与方法定义中的数据类型相同,否则报错。
示例代码如下:
publicstaticvoidmain(String[] args) { // 方法不调用不会执行inta=sum1(10); // 报错,传入参数数量不符,需要传入2个参数intc=sum1(10,2.5); // 报错,传入参数数据类型不符,需要int型intb=sum1(20, 10); } publicstaticintsum1(inta, intb) { returna+b; }
6.有返回值的方法调用时可以选择定义变量接收结果,或者直接输出调用,甚至直接调用;无返回值方法的调用只能直接调用。
示例代码如下:
publicstaticvoidmain(String[] args) { // 6.有返回值的方法调用时可以选择定义变量接收结果,或者直接输出调用,甚至直接调用;无返回值方法的调用只能直接调用。// 定义变量接收inta=sum2(100, 200); // 300// 输出调用System.out.println(sum2(1000,2000)); // 3000// 直接调用(调用方法,让程序跑一下,不接收返回结果)sum2(150,150); // 300// 无返回值的方法只能直接调用,否则报错print1(); //打印HelloWorld// int c = print1(); // 报错,需要返回数据类型为int的数据,print1()方法无返回值 } publicstaticintsum2(inta, intb) { returna+b; } publicstaticvoidprint1() { System.out.println("HelloWorld"); }
4.方法案例
方法定义技巧说明
如上图所示,修饰符:public static (暂时固定的)
方法名称:自己取名,有意义,英文小写,驼峰模式。(有意义的名字即可)
方法体代码:完成自己需要写的功能代码即可。(具体需求具体实现)
真正需要关注的就两点:
1、分析方法是否需要声明返回值类型;2、分析方法是否需要接收参数。
4.1计算1-n的和并返回
需求:定义一个方法,方法中计算出1-n的和并返回。
分析:
1.根据格式编写方法-->因n不固定,因此需要声明形参接收,且需要返回结果,还需要声明返回值类型。
2.方法内部使用for循环计算出1-n的和并返回。
示例代码如下:
publicstaticvoidmain(String[] args) { System.out.println("1-100的和是"+add(100)); // 5050 } publicstaticintadd(intn) { intnumber=0; for (inti=1; i<=n; i++) { number+=i; } returnnumber; }
4.2判断整数是奇数还是偶数
需求:拿一个整数,然后调用方法,把整数交给方法,在方法中输出该数为奇数还是偶数
分析:
1.根据格式编写方法--> 因要传入数据给方法,方法需要声明形参接收。
2.方法内部使用if语句判断,并输出对应的结论。
示例代码如下:
publicstaticvoidmain(String[] args) { intdata=99; intdata2=100; check(data); System.out.println("----------"); check(data2); } publicstaticvoidcheck(inta) { if (a%2==0) { System.out.println(a+"为偶数"); } else { System.out.println(a+"为奇数"); } }
4.3数组求最值案例改方法形式
需求:把找出数组的最大值案例,改造成方法,可以支持返回任意整型数组
的最大值数据。
分析:
1.根据格式编写方法
要返回最大值,需要声明返回值类型。
需要接收数组,需要声明形参列表。
2.方法内部找出数组的最大值并返回。
示例代码如下:
publicstaticvoidmain(String[] args) { int[] ages= {12, 20, 33, 18, 15}; intmax=gerArrayMax(ages); System.out.println("数组中的最大值为"+max); } publicstaticintgerArrayMax(int[] arr) { // 形参传入的是堆内存中new出来的数组对象的地址// 找出数组中的最大值,并返回intmax=arr[0]; for (inti=1; i<arr.length; i++) { // 遍历数组中的每个索引的元素值// 若某个索引的元素值大于当前最大值,则将该元素值设为最大值if (arr[i] >max) { max=arr[i]; } } returnmax; }
5.方法调用的内存图
方法调用流程-内存图解
方法没有被调用的时候,在方法区中的字节码文件中存放
方法被调用的时候,需要进入到栈内存中运行。
具体执行流程示例如下图所示:
上图中程序的一般执行步骤为:
Step1:在方法区加载.class文件,里面包含程序中的四个方法main(),study(),sleep(),和eat()。
Step2:main()方法是程序运行的入口。首先会把main()方法添加到栈内存中,执行main()方法。
Step3:在main()方法执行过程中,调用study()方法,将study()方法添加到栈内存中,执行study()方法。
Step4:在study()方法执行过程中,调用eat()方法,将eat()方法添加到栈内存中,执行eat()方法,打印出“吃饭”,eat()方法执行完毕,执行完毕后将eat()方法从栈内存中移除。
Step5:调用完毕eat()方法后,study()方法继续向下执行,打印出“学习”
Step6:打印完毕后,再继续向下执行,调用sleep()方法,将sleep()方法添加到栈内存中,执行sleep()方法,打印出“睡觉”,sleep()方法执行完毕,执行完毕后将sleep()方法从栈内存中移除。
Step7:调用完毕sleep()方法后,study()方法执行完毕,将study()方法从栈内存中移除。
Step8:调用完毕study()方法后,main()方法执行完毕,将main()方法从栈内存中移除,程序结束。
6.方法的参数传递机制
6.1基本类型的参数传递
Java的参数传递机制:值传递
在传输实参给方法的形参的时候,并不是传输实参变量本身,而是传输实参变量中存储的值(方法内部中对于形参的任何改变不影响原实参,因为只传输的值,而不是传输的实参变量),这就是值传递。
实参:如在方法内部定义的变量。
形参:如在定义方法时,“()”中所声明的参数。
示例代码如下:
publicstaticvoidmain(String[] args) { inta=10; // 实参a,与方法中传入的形参a仅仅是名字一样,没有任何关系change(a); System.out.println(a); // 10,在进行参数传递时,仅仅将实参a的值10传入change()方法中,对于实参a没有任何改变,其自身值仍为10 } publicstaticvoidchange(inta) { // 形参aSystem.out.println(a); // 10a=20; System.out.println(a); // 20 }
6.2引用类型的参数传递
引用类型的参数传递与基本类型的参数传递原理相同,都是把存放在实参内的具体值赋给形参,然而二者的不同点是,引用类型的实参内的具体值,存放的是引用对象的地址,因此在进行引用类型的参数传递时,也是将具体值(地址)传给形参。后续方法内是对形参中存放的引用对象的地址进行访问或操作的。
示例代码如下:
publicstaticvoidmain(String[] args) { int[] arr= {10, 20, 30}; change(arr); System.out.println(arr[1]); // 100 获取打印堆内存中new出来的这个数组对象第2个索引位置的值,在change()方法中已经被改变 } privatestaticvoidchange(int[] arr) { // 将实参arr中存放的new出来的数组的地址的具体值传给形参arr,后续通过该地址访问System.out.println(arr[1]); // 20arr[1] =100; System.out.println(arr[1]); // 100 通过传递的地址值,改变了堆内存中new出来的这个数组对象第2个索引位置的值 }
基本类型与引用类型的参数传递的区别?
二者进行参数传递时都是通过值传递的方法,区别就是基本类型的参数传递,传的是参数的具体值,引用类型的参数传递,传递的也是具体值,只不过这个值是一个地址,再通过这个地址访问数据。
就像文件的分享一样,基本类型的参数传递是把我的文件复制、粘贴,通过拷贝的方式给你一份,我给你的是文件,无论你怎么改你自己这份文件,都和我没关系,影响不到我。而引用类型的参数传递,就像我把这份文件上传共享文档,我给你的是这份文档的网址,你通过打开网址的方式,来读取或者编辑这份文件,如果对文件有了改动,那我打开这个网址的时候就文件也会相应变化,变的是网址中文件的内容,但是打开该文件的网址没有任何变化。
7.方法的参数传递案例
7.1打印数组内容
需求:
设计一个方法用于输出任意整型数组的内容,要求输出成如下格式:
“该数组内容为:[11, 22, 33, 44, 55]”
分析:
1、定义一个方法,要求该方法能够接收数组,并输出数组内容。-->需要参数,不需要声明返回值类型
2、定义一个静态初始化的数组,调用该方法,并传入该数组。
示例代码如下:
publicstaticvoidmain(String[] args) { int[] array= {10, 25, 33, 14, 88}; printArray(array); // 调用printArray方法,打印整型数组内容 该数组内容为:[10,25,33,14,88]int[] array2=null; // 该数组内容为:[]printArray(array2); int[] array3= {}; printArray(array3); // 该数组内容为:[] } // 打印整型数组内容的方法publicstaticvoidprintArray(int[] arr) { System.out.print("该数组内容为:["); // 遍历并打印出数组中每一个元素值// for (int i = 0; i < arr.length; i++) {// if (i != arr.length - 1) {// System.out.print(arr[i] + ",");// } else {// System.out.print(arr[i]);// }// }if (arr!=null&&arr.length>0) { // 判断数组不为空或长度大于0时,打印数组内容,否则跳过// 遍历并打印出数组中每一个元素值(优化写法)for (inti=0; i<arr.length; i++) { System.out.print(i==arr.length-1?arr[i] : arr[i] +","); } } System.out.println("]"); }
7.2从数组中查询元素的索引返回
需求:设计一个方法可以接收整型数组,和要查询的元素值;最终要返回元素在该数组中的索引,如果数组中不存在该元素则返回-1。
分析:
1、定义方法,接收整型数组,查询的元素值,在方法体中完成元素查询的功能。--->需要参数、返回值
2、定义数组,调用该方法,并指定要搜索的元素值,得到返回的结果输出。
示例代码如下:
publicstaticvoidmain(String[] args) { intdata=25; int[] ages= {25, 20, 22, 12, 28}; intdataIndex=getDataIndex(data, ages); // 调用查找数组中数据索引位置的方法,获取返回值if (dataIndex!=-1) { System.out.println(data+"在数组中的索引为:"+dataIndex); } else { System.out.println(dataIndex); } } /*** create by: 全聚德在逃烤鸭、* description: 定义一个方法,从数组中查询元素的索引返回,若不存在,返回-1。参数:数组、要查询的数据 返回值:整型* create time: 2022/3/29 0029 9:56** @param data* @param arr* @return int*/publicstaticintgetDataIndex(intdata, int[] arr) { for (inti=0; i<arr.length; i++) { if (data==arr[i]) { returni; // break; // return返回调用该方法的语句,该方法直接结束,循环也就相应结束,不用再添加beak; } } return-1; // 如果循环遍历后,没有符合条件的索引,则返回-1 }
7.3比较两个数组内容是否一样
需求:如果两个数组的类型,元素个数,元素顺序和内容是一样的我们就认为这2个数组是一模一样的。
请使用方法完成:能够判断任意两个整型数组是否一样,并返回true或者false。
分析:
1、定义方法,接收2个整型数组,-->需要参数、返回值
2、在方法内部完成判断的逻辑,并返回布尔结果。
示例代码如下:
publicstaticvoidmain(String[] args) { int[] ages1= {10, 20, 320, 40}; int[] ages2= {10, 20, 30, 40}; booleanisSame=checkArraySame(ages1, ages2); if (isSame) { System.out.println("两个数组内容一样"); } else { System.out.println("两个数组内容不一样"); } } /*** create by: 全聚德在逃烤鸭、* description: 定义一个方法,比较两个整型数组内容是否一样,一样返回true,否则返回false 参数:两个整型类型 返回值:布尔型* create time: 2022/3/29 0029 10:15** @param arr1* @param arr2* @return boolean*/publicstaticbooleancheckArraySame(int[] arr1, int[] arr2) { // 判断两个数组长度是否一致,若不一致则返回falseif (arr1.length!=arr2.length) { returnfalse; } // 判断两个数组中各个元素值大小及顺序是否一致,若不一致则返回falsefor (inti=0; i<arr1.length; i++) { if (arr1[i] !=arr2[i]) { returnfalse; } } returntrue; // 两个数组长度、各个元素值大小及顺序均一致,返回true }
8.方法重载
8.1方法重载的形式、作用
方法重载的定义
同一个类中,出现多个方法名称相同,但是形参列表是不同的方法,那么这些方法就是重载方法。
调用方法的时候,会通过参数的不同来区分调用的是哪个方法。
示例代码如下:
publicstaticvoidmain(String[] args) { fire(); // 默认向x地发射1枚武器fire("A地"); // 默认向A地发射1枚武器fire("A地", 100); // 默认向A地发射100枚武器 } publicstaticvoidfire() { System.out.println("默认向x地发射1枚武器"); } publicstaticvoidfire(Stringlocation) { System.out.println("默认向"+location+"发射1枚武器"); } publicstaticvoidfire(Stringlocation, intnumbers) { System.out.println("默认向"+location+"发射"+numbers+"枚武器"); }
方法重载的作用
可读性好,方法名称相同提示是同一类型的功能,通过形参不同实现功能差异化的选择,这是一种专业的代码设计。
重载的方法还可以调用其他的方法,来减少代码的开发工作量,使代码更加简洁。
如在上例中可以在调用fire()方法时,在方法内部调用fire(String location)方法,在调用fire(String location)方法时,在方法内部调用fire(String location, int numbers)方法
示例代码如下:
publicstaticvoidmain(String[] args) { fire(); // 默认向x地发射1枚武器fire("A地"); // 默认向A地发射1枚武器fire("A地", 100); // 默认向A地发射100枚武器 } publicstaticvoidfire() { fire("x地"); // 调用fire(String location)方法 } publicstaticvoidfire(Stringlocation) { fire(location, 1); // 调用fire(String location, int numbers)方法 } publicstaticvoidfire(Stringlocation, intnumbers) { System.out.println("默认向"+location+"发射"+numbers+"枚武器"); }
8.2方法重载的识别技巧
1.只要是同一个类中,方法名称相同、形参列表不同,那么他们就是重载的方法,其他都不管。
修饰符,返回值类型都无所谓
2.形参列表不同指的是:形参的个数、类型、顺序不同,不关心形参的名称。
示例代码如下:
// 新方法publicstaticvoidopen() { } // 重载方法publicstaticvoidopen(inta) { // 形参的个数不同 } // 重载方法publicstaticvoidopen(inta, intb) { // 形参的个数不同 } // 重载方法publicstaticvoidopen(doublea, intb) { // 形参的类型不同 } // 重载方法publicstaticvoidopen(inta, doubleb) { // 形参的顺序不同 } // 重复方法// public static void open(int i, double d) { // 形参的个数、类型、顺序均相同,形参的名称无所谓//// }// 新方法publicstaticvoidOPEN() { // 方法名称不同 }
9.补充知识:单独使用return关键字
return;-->可以立即跳出并结束当前方法的执行;
return关键字单独使用可以放在任何方法中。
return只会结束当前所在方法,不会结束上级调用方法。
示例代码如下:
publicstaticvoidmain(String[] args) { System.out.println("main()方法开始"); division(10, 0); System.out.println("main()方法结束"); // return只会结束当前所在方法,不会结束上级调用方法 } publicstaticvoiddivision(inta, intb) { if (b==0) { System.out.println("输入数据有误,除数不能为0!"); return; // 立即跳出并结束当前方法的执行,返回上级调用该方法的语句 } intc=a/b; System.out.println("结果是"+c); }
易混淆知识点—return、break、continue的执行特点:
return;跳出并立即结束所在方法的执行。
break;跳出并结束当前所在循环的执行。
continue;结束当前所在循环的当次继续,进入下一次执行。