第6章方法Java程序设计2学习目标学习如何在类中建立方法理解方法调用、参数传递和重载方法6.1定义方法Java语言定义方法的语法结构如下:1.返回值方法的返回值是指方法运行结束时产生的一个结果,返回值类型说明了方法返回值的数据类型。如果一个方法只是执行某些特定的操作,不产生返回值,则返回值类型为关键字void,该类方法称为void方法。2.方法名方法名使用Java语言标识符命名。建议方法名用一个动词或动词短语,命名时采用小写字母,当由多个单词构成时,从第二个单词开始首字母大写。3.形式参数形式参数(简称形参)列表定义了方法为完成特定功能而需要的数据个数和它们的类型。当调用方法时形参接收相应的数据。形参列表指明了形参的数量、类型和顺序,对于每个形参需要独立的数据类型说明。4.方法体方法体中包含方法为完成功能而需要的语句集合。产生返回值的方法中需要使用语句:return表达式;该语句的作用是终止方法的执行,并将其表达式的值作为方法的返回值。返回值类型为void的方法中可以不使用return语句,这种情况下,方法将执行完最后一条语句时终止;如果在void方法中使用return语句,则不能带有表达式,只具有终止方法执行的作用。6.2调用方法定义方法的目的是在程序中使用它,在程序中使用方法称为调用方法。根据方法是否有返回值可以把方法调用分成两类:方法调用表达式和方法调用语句。1.方法调用表达式方法调用表达式形式用于对有返回值方法的调用,将方法调用作为一个表达式或表达式的一部分。这种调用的目的就是要使用方法调用产生的返回值。举例:intbig=max(10,100);//max方法调用的值被赋值给变量System.out.println(max(10,100));//max方法调用的值被输出intsum=max(x,y)+200;//max方法调用的值参与算术运算2.方法调用语句void方法的调用必须采用语句形式。例如:System.out.println(welcometojava);//调用void方法的语句注意事项:①方法调用时出现在括号内的常量、变量或表达式称为实际参数,简称实参。其作用是向形参提供数据。②Java语言也允许以语句形式调用有返回值的方法,此时方法的返回值被忽略了。如果程序对某个方法的返回值不感兴趣,可以采用语句形式调用。③方法调用的执行流程一个方法中调用另一个方法时,程序的流程从发生方法调用的位置离开转移到被调用的方法,当被调用方法中碰到return或执行完最后一条语句时,程序流程重新回到调用者方法继续后面操作的执行下面是void方法的调用流程示例图:6.3参数的值传递在调用定义了形参的方法时需要把实参的值传递给形参,Java语言规定:①实参必须与方法定义中的形参在次序和数量上匹配,在数据类型上兼容。数据类型兼容是指实参与形参的数据类型相同或者实参不必经过强制类型转换就可以将值赋给形参。②实参向形参的传递数据是单向值传递。只能是实参将值传递给形参,在被调用方法的执行过程中,无论形参的值发生怎样变化都不会反过来影响实参的值。举例://文件名:ParameterPass.javapublicclassParamterPass{publicstaticvoidmain(String[]args){intx=10,y=100;System.out.printf(调用swap方法之前:x=%d,y=%d\n,x,y);swap(x,y);System.out.printf(调用swap方法之前:x=%d,y=%d\n,x,y);}publicstaticvoidswap(inta,intb){inttemp;System.out.println(\t在swap方法内:);System.out.printf(\t\t交换a,b之前:a=%d,b=%d\n,a,b);temp=a;a=b;b=temp;System.out.printf(\t\t交换a,b之后:a=%d,b=%d\n,a,b);}}运行结果:从上图所示的程序运行结果中可以发现,形参数值的变化对实参的数值没有影响。6.4方法重载Java语言允许在一个类中的两个或更多的方法具有相同的方法名称但有不同的形式参数列表,称为方法重载。首先实参和形参的数量必须相同,然后考虑以下几种情况:(1)如果找到1个形参与实参的类型完全相同的方法,则调用该方法;(2)否则,如果找到1个需要通过自动类型类型转换可以进行参数传递的方法,则调用该方法;(3)否则,如果找到多个需要通过自动类型类型转换可以进行参数传递的方法,并且其中一个方法的形参与实参最接近,则调用该方法;(4)否则,如果找到多个需要通过自动类型类型转换可以进行参数传递的方法,但其中形参与实参最接近的方法多于1个,则无法调用,编译出错。//文件名:MethodOverloading.javapublicclassMethodOverloading{publicstaticvoidmain(String[]args){intx;doubley;//参数完全匹配的调用x=max(10,100);//调用max(int,int)y=max(1.0,2.0);//调用max(double,double)y=max(1.0,2.0,3.0);//调用max(double,double,double)//需要进行类型转换的调用y=max(1.0,100);//调用max(double,double)y=max(10,2.5);//调用max(double,double)y=max(1,2,3);//调用max(double,double,double)}//返回2个int数据的大值publicstaticintmax(inta,intb){returnab?a:b;}//返回2个double数据的大值publicstaticdoublemax(doublea,doubleb){returnab?a:b;}//返回3个double数据的大值publicstaticdoublemax(doublea,doubleb,doublec){returnmax(max(a,b),c);}}方法重载可以使程序清晰易读,并减少记忆方法名称的难度。定义完成相似任务的方法时应该使用重载,即给予相同的方法名和不同的形参列表。需要注意的是,方法的返回值类型和修饰符不能作为重载方法时区别方法的依据。6.5方法与数组调用方法和被调用方法之间传递数组的本质是传递数组变量的值。由于数组变量中存放的是数组地址,因此参数传递和返回值都是数组的地址,而不是数组本身。举例:编写方法通过形参接收一个int类型数组,并将数组的元素进行逆序存放。//文件名:ReverseArray.javapublicclassReverseArray{publicstaticvoidmain(String[]args){int[]list1={1,2,3,4,5,6,7,8,9,0};System.out.print(调用reversInSameArray前,list1:);outputArray(list1);reverseInSameArray(list1);System.out.print(调用reversInSameArray后,list1:);outputArray(list1);int[]list2={1,2,3,4,5,6,7,8,9,0};int[]list3=null;System.out.print(调用reverseInNewArray前,list2:);outputArray(list2);list3=reverseInNewArray(list2);System.out.print(调用reverseInNewArray后,list2:);outputArray(list2);System.out.print(调用reverseInNewArray后,list3:);outputArray(list3);}//输出一个数组所有元素的方法,本方法没有改变数组变量array的值,//也没有改变数组的内容publicstaticvoidoutputArray(int[]array){for(intvalue:array){System.out.print(value+);}System.out.println();}//在原数组中进行元素逆序的方法,本方法没有改变数组变量的值,但改变了数组的内容publicstaticvoidreverseInSameArray(int[]array){for(inti=0,j=array.length-1;ij;i++,j--){inttemp=array[i];array[i]=array[j];array[j]=temp;}}//产生一个与原数组元素逆序的新数组,本方法改变了数组变量的值,//但没有改变原数组的内容publicstaticint[]reverseInNewArray(int[]array){int[]old=array;array=newint[old.length];for(inti=0,j=array.length-1;iold.length;i++,j--){array[i]=old[j];}returnarray;}}运行结果:调用reverseInSameArray方法后,实参数组变量list1对应的数组的内容发生了变化,而调用reverseInNewArray方法后实参数组变量list2对应的数组的内容没有发生变化。调用reverseInSameArray方法的过程如下图所示:调用reverseInNewArray方法的过程如下图所示:通过上述分析,对于数组作为方法调用的参数和返回值,可以得到以下结论:(1)数组作为参数和返回值的实质是数组变量作为参数的返回值,传递的是数组的地址,而不是数组本身。(2)由于实参和形参数组变量访问同一数组,被调用方法中用形参修改数组的内容就是实参访问的数组发生了变化。但是如果让形参数组变量去访问另外一个数组,对实参数组变量是没有影响的。(3)在被调用方法中创建新的数组,该数组的地址可以对过返回值传递给调用方法中的数组变量,从而在调用方法中也可以访问该数组。6.6局部变量局部变量是指在方法内部定义的变量。局部变量根据其在方法内的定义位置不同而具有不同的作用域。一个变量的作用域是程序中的某个范围,在此范围内的语句可以使用该变量。局部变量的作用域是从该变量的定义语句开始到包含该变量定义语句的最内层的块结束为止。局部变量必须先定义后使用。方法的形式参数也是该方法的一个局部变量,其作用域为整个方法体。Java语言允许在一个方法中两个不存在嵌套关系的语句块中定义同名局部变量,但是禁止在相互嵌套的两个语句块中定义同名局部变量。6.7方法的递归调用递归是一个数学概念,是指函数直接或间接的调用自己的过程,如阶乘的定义。Java语言中方法的递归调用是指在方法体中直接或间接的调用方法自身。例6-5:编写递归方法,对给定的正整数计算其阶乘。n!=f(n)=n*f(n-1)n0n!=1n=0//文件名:ComputeFactorial.javaimportjava.util.Scanner;publicclassComputeFactorial{publicstaticvoidmain(String[]args){Scannerinput=newScanner(System.in);longn=input.nextLong();longfac=factorial(n);System.out.println(n+!=+fac);}publicstaticlongfactorial(longn){if(n==0){return1;}else{returnn*factorial(n-1);}}}可以看到递归方法的定义是非常简洁的,但是其递归调用过程相对复杂。递归方法在定义时需要