第六章 方法
6.1 引言
方法可以用于定义可重用的代码以及组织和简化编码。
方法的作用就是为了减少重复代码编写的冗余,同时也是模块化开发的一种重要思想的应用。
假如需要分别求出从1到10、从20到37以及从35到49的整数和,可以编写如下代码:
int sum = 0;
for (int i = 1; i <= 10; i ++)
sum += i;
System.out.printin("Sum from 1 to 10 is " + sum);
sum = 0;
for(int i = 20; i <= 37; i ++)
Sum += i;
System.out.printin("Sum from 20 to 37 is " + sum);
sum = 0:
for(int i = 35; i <= 49; i ++)
sum += i;
System.out.printin("Sum from 35 to 49 is " + sum);
我们发现计算从1到10、从20到37以及从35到49的整数和,除了开始的数和结尾的数不同之外,其他都是非常类似的。因此,我们可以一次性地编写好通用的代码而无须重新编写。通过定义和调用方法实现该功能。
上面的代码可以简化为如下所示:
public static int sum(int i1,int i2) {
int result = 0;
for(int i = i1; i <= i2; i ++)
result += i;
return result;
}
public static void main(String[]args){
System.out.printin("Sumfrom 1 to 10 is" + sum(1,10));
System.out.printin("Sumfrom 20 to 37 is"+ sum(20,37));
System.out.printin("Sumfrom 35 to 49 is"+ sum(35,49));
}
方法是为完成一个操作而组合在一起的语句组。在前面的章节里,已经使用过预定义的方法,例如:System.out.printIn
、System.exit
、Math.pow
和Math.random
,这些方法都在Java库中定义。在本章里,我们将学习如何定义自己的方法以及应用方法抽象来解决复杂问题。
6.2 定义方法
方法的定义由方法名称、参数、返回值类型以及方法体组成。
定义方法的语法如下所示:
修饰符 返回值类型 方法名 (参数列表) {
//方法体
}
我们来看一个方法的定义,该方法找出两个整数中较大的数。这个名为max的方法有两个int型参数:num1和num2,方法返回两个数中较大的一个。图6-1解释了这个方法的组成。
方法头(method header)是指方法的修饰符(modifier)、返回值类型(return value type)、方法名(method name)和方法的参数(parameter)。
方法可以返回一个值。returnValueType
是方法返回值的数据类型。有些方法只是完成某些操作而不返回值。
如果方法有返回值,则称为带返回值的方法(value-returning method),否则就称这个该方法为空方法(void method)。
定义在方法头中的变量称为形式参数(formal parameter)或者简称为形参(parameter)参数就像占位符。当调用方法时,就给参数传递一个值,这个值称为实际参数(actual parameter)或实参(argument)。参数列表(parameter list)指明方法中参数的类型、顺序和个数。方法名和参数列表一起构成方法签名(method signature)。参数是可选的,也就是说方法可以不包含参数。
注意:在某些语言中,方法称为过程(procedure)或函数(function)。这些语言中,带返回值的方法称为函数,返回值类型为void的方法称为过程。
警告:在方法头中,需要对每一个参数进行单独的数据类型声明。
例如:max(int num1, int num2)
是正确的,而max(int num1, num2)
是错误的。
注意:我们经常会说“定义方法”和“声明变量”,这里我们谈谈两者的细微差别。定义给出了被定义的项是什么,而声明通常是指为被声明的项分配内存以存储数据。
6.3 调用方法
方法的调用是指执行方法中的代码。
方法定义给出了方法的作用。要使用方法,必须调用(call或invoke)它。根据方法是否有返回值,调用方法有两种途径。
如果方法返回一个值,对方法的调用通常就当作一个值处理。例如:
int larger = max(3,4);
如果方法返回void
,对方法的调用必须是一条语句。例如:
System.out.printin("Welcome to Java!");
注意:在Java中,带返回值的方法也可以当作语句调用。这种情况下,函数调用者只需忽略返回值即可。虽然很少这么做,但是如果调用者对返回值不感兴趣,这样也是允许的。
6.5 按值传参
调用方法的时候是通过传值的方式将实参传给形参的。
方法的强大之处在于它处理参数的能力。调用方法时,需要提供实参,它们必须与方法签名中所对应的形参次序相同。这称作参数顺序匹配(parameter order association)。
警告:实参必须与方法签名中定义的形参在次序和数量上匹配,在类型上兼容。类型兼容是指不需要经过显式的类型转换,实参的值就可以传递给形参,例如,将int型的实参值传递给 double型形参。
当调用带参数的方法时,实参的值传递给形参,这个过程称为按值传递(pass-by-value)。如果实参是变量而不是字面值,则将该变量的值传递给形参。无论形参在方法中是否改变,该变量都不受影响。
为简化起见,Java程序员经常说将实参x传给形参y,实际含义是指将x的值传递给y。
6.6 模块化代码
模块化使得代码易于维护和调试,并且使得代码可以被重用。
使用方法可以减少冗余的代码,提高代码的复用性。方法也可以用来模块化代码,以提高程序的质量。
6.8 重载方法
重载方法使得你可以使用同样的名字来定义不同方法,只要它们的参数列表是不同的。
方法重载(method overloading)指在一个类中有两个方法,它们具有相同的名字,但有不同的参数列表。Java编译器根据方法签名决定使用哪个方法。
6.9 变量的作用域
变量的作用域(scope of a variable)是指变量可以在程序中被引用的范围。
在方法中定义的变量称为局部变量(local variable)。局部变量的作用域是从变量声明的地方开始,直到包含该变量的块结束为止。局部变量都必须在使用之前进行声明和赋值。参数实际上就是一个局部变量。一个方法的参数的作用域涵盖整个方法。
可以在一个方法中的不同块里声明同名的局部变量,但是,不能在嵌套块中或同一两次声明同一个局部变量。
6.10 示例学习:生成随机字符
**需求:**写一个随机生成字符的程序,可以随机生成175个字符,并且每行25个。
具体实现:
package com.Javabook.Demo;
public class P200_RandomCharacter {
//在ch1和ch2之间生成一个随机字符
public static char getRandomCharacter(char ch1, char ch2) {
return (char) (ch1 + Math.random() * (ch2 - ch1));
}
//随机生成一个小写字母
public static char getRandomLowerCaseLetter() {
return getRandomCharacter('a', 'z');
}
//随机生成一个大写字母
public static char getRandomUpperCaseLetter() {
return getRandomCharacter('A', 'Z');
}
//随机生成一个数字
public static char getRandomDigitCharacter() {
return getRandomCharacter('0', '9');
}
//随机生成一个字符
public static char getRandomCharacter() {
return getRandomCharacter('\u0000', '\uFFFF');
}
}
package com.Javabook.Demo;
public class P201_TestRandomCharacter {
//程序主入口
public static void main(String[] args) {
final int NUMBER_OF_CHARS = 175;
final int CHARS_PER_LINE = 25;
//打印'a' ~ 'z'之间的随机字符,每行25个字符
for (int i = 0; i < NUMBER_OF_CHARS; i++) {
char ch = P200_RandomCharacter.getRandomLowerCaseLetter();
if ((i + 1) % CHARS_PER_LINE == 0) {
System.out.println(ch);
} else {
System.out.print(ch);
}
}
}
}