方法
方法可以用于定义可以重用的代码以及组织和简化代码,是为了完成一个操作而组合在一起的语句组。
定义方法
方法的定义由方法名称、参数、返回值类型以及方法体组成。
修饰符 返回值类型 方法名(参数列表){
//方法体
}
方法头(method header)是指方法的修饰符(modifier)、返回值类型(return value type)、方法名(method name)和方法的参数(parameter)。接下来所说的均是使用静态修饰符static。
方法可以返回一个值。returnValueType是方法返回值的数据类型。有些方法只是完成某些要求的操作,而不要求返回值这种情况下,returnValueType为关键字void。例如在main方法中returnValueType就是void。如果有返回值,则称为带返回值的方法(value-return method),否则为void方法(void method)。
定义在方法头中的变量称为形式参数(formal parameter)或者称为形参(parameter)。参数就像占位符。当调用方法时,就给参数传递一个值,这个值称为实际参数(actual parameter)或实参(argument)。参数列表(parameter list)指明方法中参数的类型、顺序和个数。方法名和参数列表一起构成方法签名。参数是可选的,也就是说方法可以不包含参数。
为了使返回值的方法能返回一个结果,必须要使用带关键字return 的返回语句。执行return语句时方法终止。
在方法中,需要对每一个参数进行独立的数据类型声明。如max(int num1, int num2)是正确的,而max(int num1,num2)是错误的。
定义某某是指被定义的条目是什么,而声明通常是指为被声明的条目分配内存来存满存储数据。
调用方法
即执行方法中的代码。
在定义方法中,定义方法要做什么,为了使用方法,必须调用它。根据是否有返回值,调用方法有两种途径。
如果方法返回一个值,对方法的调用通常就当作一个值处理。例如:int larger = max(3,4);
如果方法返回void,对方法的调用必须是一条语句。例如,println方法返回void。System.out.println("Welcome to java!")
注意:在java中,带返回值的方法也可以当作语句调用。这种情况下,函数调用者只需忽略返回值即可。
public class TestMax{
public static void main(String[] args){
int i = 5;
int j = 2;
int k = max(i, j);
System.out.praintln("The maximun of" + i + " and " + j + " is " + k);
}
public static int max(int num1, int num2){
int result;
if (num1 > num2)
result = num1;
else
result = num2;
return result;
}
}
这个程序包括了main方法和max方法。main方法与其他方法很类似,区别在于它是Java虚拟机调用的。
main方法的方法头永远都是一样的。包括修饰符public和static,返回值类型void,方法名main,String[] 类型的参数。String[] 表明参数是一个String型数组。
main中的语句可以调用main方法所在类中定义的其他方法,也可以调用别的类中定义的方法。
当调用max方法时,控制流程转给max方法。一旦max方法结束,将控制返回给调用者。
方法能够带来代码的共享和重用。除了可以在TestMax中调用max方法,还可以在其他类中调用它。如果创建了一个新类,可以通过使用“类名 . 方法名”(即TestMax.max)来调用max方法。
每当调用一个方法时,系统会创建一个活动记录(也称为活动框架),用于保存方法中的参数和变量。活动记录置于一个内存区域中,称为调用堆栈。调用堆栈也称为执行堆栈、运行时堆栈,或者一个机器堆栈,简称为“堆栈”。当一个方法调用另一个方法时,调用者的活动记录保持不动,一个新的活动记录被创建用于被调用的新方法。一个方法结束返回到调用者时,其相应的活动记录也被释放。
理解调用堆栈有助于理解方法是如何调用的。main方法定义的变量是i、j和k;max方法中定义的变量是num1、num2和result。定义在方法签名中的变量num1和num2都是方法max的参数。他们的值通过方法调用进行传递。
void方法示例
void方法不返回值
package demo2;
public class TestReturnGradeMethod {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.print("The grade is " + getGrade(78.5));
System.out.print("The grade is " + getGrade(59.5));
}
public static char getGrade(double score){
if (score >= 90.0)
return 'A';
else if (score >= 80.0)
return 'B';
else if (score >= 70.0)
return 'C';
else if (score >= 60.0)
return 'D';
else
return 'F';
}
}
void语句不需要return语句,但他能用于终止方法并返回到方法的调用者。语法是 return;
这种做法很少用,但是对于改变void方法中的正常流程控制是很有用的。例如:当分数是无效值时,下列代码就用return语句结束方法。
通过传值进行参数传递
调用方法的时候是通过传值的方式将实参传给形参的。
调用方法时,需要提供实参,他们必须与方法签名中所对应的形参次序相同。这叫做参数顺序匹配(parameter order association)。
public static void nPrintln(String message, int n){
for(int i=0;i<n;i++);
}
调用的时候需要按照顺序,nPrintln(“Hello”, 3)
实参必须与方法签名中定义的参数在次序和数量上匹配,在类型上兼容。类型兼容是指不需要经过显式的类型转换,实参的值就可以传递给形参。例如,将int型的实参值传递给double型形参。
当调用带参数的方法时,实参的值传递给形参,这个过程称为按值传递(pass-by-value)。如果实参是变量而不是直接量,则将该变量的值传递给形参。无论形参在方法中是否改变,该变量都不受影响。
public class Incerement {
public static void main(String[] args) {
// TODO Auto-generated method stub
int x = 1;
System.out.println("Before the call, x is " + x);
increment(x);
System.out.println("After the call, x is " + x);
}
public static void increment(int n) {
n++;
System.out.println("n inside the method is " + n);
}
}
public class TestPassByValue {
public static void main(String[] args) {
// TODO Auto-generated method stub
int num1 = 1;
int num2 = 2;
System.out.println("Before invoking the swap method, num1 is " + num1 + " and num2 is " + num2);
swap(num1, num2);
System.out.println("After invoking the swap method , num1 is " + num1 + " and num2 is " + num2);
}
public static void swap (int n1, int n2) {
System.out.println("\tInside the swap method");
System.out.println("\t\tBefore swapping, n1 is " + n1 + " and n2 is " + n2);
int temp = n1;
n1 = n2;
n2 = temp;
System.out.println("\t\tAfter swapping, n1 is " + n1 + " and n2 is " + n2);
}
}
模块化代码
模块化易于维护和调试,并且使得代码可以被重用。
import java.util.Scanner;
public class Test2 {
private static String number1;
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
System.out.print("Enter first integer: ");
int number1 = input.nextInt();
System.out.print("Enter second integer: ");
int number2 = input.nextInt();
System.out.print("The greatest common divisor for " + number1 + " and" + number2 + " is " + gcd(number1, number2));
}
public static int gcd(int n1, int n2) {
int n = 0;
for (int i = 2; i < n2/2 && i < n1/2; i++){
if (n1%i == 0 && n2%i ==0)
n = i;
}
return n;
}
}
import java.util.Scanner;
public class Test2 {
private static String number1;
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
System.out.print("Enter first integer: ");
int number1 = input.nextInt();
printPrimeNumber(number1);
}
public static void printPrimeNumber(int numberOfPrimes) {
int count = 0;
int number = 2;
while (count < numberOfPrimes) {
if (isPrime(number)) {
count++;
if (count % 10 == 0)
System.out.printf("%5d\n", number);
else
System.out.printf("%5d",number);
}
number++;
}
}
public static boolean isPrime(int number) {
boolean isprime = true;
for (int i = 2; i <= number/2; i++)
if (number % i == 0){
isprime = false;
break;
}
return isprime;
}
}
方法的重载
重载方法使得你可以使用同样的名字来定义不同方法,只要他们的方法签名是不同的就行。
public class Test2 {
private static String number1;
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("The maximum of 3.0 and 4 is " + max(3, 4));
System.out.println("The maximum of 3.0 and 5.4 is " + max(3.0, 5.4));
System.out.println("The maximum of 3.0, 5.4 and 10.14 is " + max(3.0, 5.4, 10.14));
}
public static int max(int num1, int num2) {
if (num1 > num2)
return num1;
else
return num2;
}
public static double max(double num1, double num2) {
if (num1 > num2)
return num1;
else
return num2;
}
public static double max(double num1, double num2, double num3) {
return max(max(num1, num2), num3);
}
}
如果调用int参数的max方法,就将调用需要int型参数的max方法;如果调用带double型参数的max方法,就将调用double型参数的max方法。这就是方法重载(method overloading)。也就是说,在一个类中有两个方法,他们具有相同的名字,但有不同的参数列表。java编译器根据方法签名决定使用哪个方法。
public class Test2 {
private static String number1;
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("The maximum of 3.0 and 4 is " + max(3, 4));
System.out.println("The maximum of 3.0 and 5.4 is " + max(3.0, 5.4));
System.out.println("The maximum of 3.0, 5.4 and 10.14 is " + max(3.0, 5.4, 10.14));
}
public static int max(int num1, int num2) {
if (num1 > num2)
return num1;
else
return num2;
}
public static double max(double num1, double num2) {
if (num1 > num2)
return num1;
else
return num2;
}
public static double max(double num1, double num2, double num3) {
return max(max(num1, num2), num3);
}
}
当调用max(3,4)时,调用的是求两个整数中较大值得max方法。当调用max(3.0,5.0)时,调用的是求两个双精度数中较大值的max方法。第仨个同理。
当然,也可以像max(2,3.5)这样一个int值和一个double值得max方法,这个会调用第二个max方法,第一个参数值被自动转换为double值,然后传递给这个方法。其实,java调用方法时,Java编译器寻找最精确的匹配的方法。也就是参数不能损失精度。
被重栽的方法必须具有不同的参数列表。不能基于不同修饰符或返田值类型来重栽方法。
注意:有时调用一个方法时,会有两个或更多可能的匹配,但是,编译器无法判断哪个是最精肩的匹配。这称为歧义调用( ambiguous invocation)。歧义调用会产生一个编译错误。
变量的作用域
在方法中定义的变量称为局部变f(local variable)。局部变量的作用域从声明变量的地方开始,直到包含该变量的块结束为止。局部变量都必须在使用之前进行声明和陚值。参数实际上就是一个局部变量。一 个方法的参数的作用域涵盖整个方法。在for 循环头中初始动作部分声明的变量,其作用域是整个 for 循环。但是在 for 循环体内声明的变量,其作用域只限于循环体,是从它的声明处开始,到包含该变量的块结束为止。
可以在一个方法中的不同块里声明同名的局部变量,但是,不能在嵌套块中或同一块中两次声明同一个局部变量。