06-方法
- 6.1 引言
- 方法可以用于定義可重用的代碼以及組織和簡化編碼。
- 6.2 定義方法
- 方法的定義由方法名稱、參數(shù)、返回值類型以及方法體組成。
- 定義方法的語法如下所示:
修飾符 返回值類型 方法名(參數(shù)列表){ //方法體; } - 方法頭是指方法的修飾符、返回值類型、方法名和方法的參數(shù)。
- 方法可以返回一個值。有些方法只是完成某些要求的操作,而不返回值。在System.exit、System.out.println方法中返回值類型也是void。如果方法有返回值,則稱為帶返回值的方法,否則就稱這個方法為void方法。
- 定義在方法頭中的變量稱為形式參數(shù)或者簡稱為形參。參數(shù)就像是占位符。當(dāng)調(diào)用方法時,就給參數(shù)傳遞一個值,這個值稱為實(shí)際參數(shù)或者實(shí)參。參數(shù)列表指明方法中參數(shù)的類型、順序和個數(shù)。方法名和參數(shù)列表一起構(gòu)成方法簽名。參數(shù)是可選的,也就是方法可以不包含參數(shù)。
- 為使帶返回值的方法能返回一個結(jié)果,必須要使用帶關(guān)鍵字return的返回語句。執(zhí)行return語句時方法終止。
- 在其他語言中,方法稱為過程或函數(shù)。這些語言中,帶返回值的方法稱為函數(shù),返回值類型是void的方法稱為過程。
- 在方法頭中,需要對每一個參數(shù)進(jìn)行單獨(dú)的數(shù)據(jù)類型聲明。
- 定義是指被定義的項(xiàng)是什么,而聲明通常是指被聲明的項(xiàng)分配內(nèi)存來存儲數(shù)據(jù)。
- 6.3 調(diào)用方法
- 為了之用方法,必須使用它。根據(jù)方法是否有返回值,調(diào)用方法有兩種途徑。
- 如果方法返回一個值,對方法的調(diào)用通常就當(dāng)做一個值處理。
- 如果方法返回void,對方法的調(diào)用必須是一條語句。
- 在Java中,帶返回值的方法也可以當(dāng)做語句調(diào)用。這種情況下,函數(shù)調(diào)用者只需要忽略返回值即可。雖然很少這么做,但是如果調(diào)用者對返回值不感興趣,這樣也是允許的。
- 當(dāng)調(diào)用一個方法時,程序控制就轉(zhuǎn)移到被調(diào)用的方法。當(dāng)執(zhí)行完return語句或執(zhí)行到表示方法結(jié)束的右括號時,被調(diào)用的方法將程序控制返還給調(diào)用者。
package chapter06; public class TestMax { public static void main(String[] args){ int i = 5; int j = 2; int k = max(i,j); System.out.println("The maximum 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; } } - 方法能夠帶來代碼的共享和重用。除了可以在TestMax中調(diào)用max方法,還可以在其他類中調(diào)用他。如果創(chuàng)建了一個新類,可以通過使用“類名.方法名”來調(diào)用max方法。
- 每當(dāng)調(diào)用一個方法時,系統(tǒng)會創(chuàng)建一個活動記錄(也稱活動框架),用于保存方法中的參數(shù)和變量?;顒佑涗浿糜谝粋€內(nèi)存區(qū)域中,稱為調(diào)用棧。調(diào)用棧也稱為執(zhí)行棧、運(yùn)行時棧,或者一個機(jī)器棧,常簡稱為棧。當(dāng)一個方法調(diào)用另一個方法時,調(diào)用者的活動記錄保持不變,一個新的活動記錄被創(chuàng)建用于被調(diào)用的新方法。一個方法結(jié)束運(yùn)行返回到調(diào)用者,其相應(yīng)的活動記錄也被釋放。
- 調(diào)用棧以后進(jìn)先出的方式來保存活動記錄。
- 6.4 void方法與返回值方法
```java
package chapter06;
public class TestVoidMethod {
public static void main(String[] args){
System.out.print("The grade is ");
printGrade(78.5);
System.out.print("The grade is ");
printGrade(59.5);
}
public static void printGrade(double score){
if (score >= 90.0){
System.out.println('A');
}
else if (score >= 80.0){
System.out.println('B');
}
else if (score >= 70.0){
System.out.println('C');
}
else if (score >= 60.0){
System.out.println('D');
}
else {
System.out.println('F');
}
}
}
```
```java
package chapter06;
public class TestReturnGradeMethod {
public static void main(String[] args){
System.out.print("The grade is " + getGrade(78.5));
System.out.print("\nThe 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';
}
}
```
- return語句對于void方法不是必須的,但他能用于方法并返回到方法的調(diào)用者。他的語法是:
```java
return;
```
- 這種用法很少,對視對于改變void方法中的正常流程控制是很有用的。
-
6.5 按值傳參
- 調(diào)用方法的時候是通過傳值的方式將實(shí)參傳遞給形參的。
- 方法的最強(qiáng)大之處在于他處理參數(shù)的能力。調(diào)用方法時,需要提供參數(shù),他們必須與方法簽名中所對應(yīng)的形參次序相同。這稱為參數(shù)順序匹配。
- 實(shí)參必須與方法簽名中定義的形參在次序和數(shù)量上匹配,在類型上兼容。類型兼容是指不需要經(jīng)過顯式的類型轉(zhuǎn)換,實(shí)參的值就可以傳遞給形參。
- 當(dāng)調(diào)用參數(shù)的方法時,實(shí)參的值傳遞給形參,這個過程稱為按值傳遞。如果實(shí)參是變量而不是字面值,則將該變量的值傳遞給形參。無論形參在方法中是否改變,該變量都不受影響。
package chapter06; public class Increment { public static void main(String[] args){ 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); } }package chapter06; public class TestPassByValue { public static void main(String[] args){ 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); } }
-
6.6 模塊化代碼
- 模塊化的代碼是的代碼易于維護(hù)和調(diào)試,并且是的代碼可以被調(diào)用。
package chapter06; import java.util.Scanner; public class GreatestCommonDivisorMethod { public static void main(String[] args){ Scanner input = new Scanner(System.in); System.out.print("Enter first integer: "); int n1 = input.nextInt(); System.out.print("Enter second integer: "); int n2 = input.nextInt(); System.out.println("The greatest common divisor for " + n1 + " and " + n2 + " is " + gcd(n1,n2)); } public static int gcd(int n1,int n2){ int gcd = 1; int k = 2; while (k <= n1 && k <= n2){ if (n1 % k == 0 && n2 % k == 0) gcd = k; k++; } return gcd; } } - 通過將求最大公約數(shù)的代碼封裝在一個方法中,這個程序就具備以下幾個優(yōu)點(diǎn):
- 1、他將計(jì)算最大公約數(shù)的問題和main方法中的其他代碼分隔開,這樣做會使得邏輯更加清晰而且程序的可讀性更強(qiáng)。
- 2、將計(jì)算最大公約數(shù)的錯誤限定在gcd方法中,這樣就縮小了調(diào)試的范圍。
- 3、現(xiàn)在,其他程序可以重復(fù)使用gcd方法。
package chapter06; public class PrimeNumberMethod { public static void main(String[] args){ System.out.println("The first 50 prime numbers are \n"); printPrimeNumbers(50); } public static void printPrimeNumbers(int numberOfPrime){ final int NUMBER_OF_PRIME_PER_LINE = 10; int count = 0; int number = 2; while (count < numberOfPrime){ if (isPrime(number)){ count++; if (count % NUMBER_OF_PRIME_PER_LINE == 0){ System.out.printf("%-5d\n",number); } else System.out.printf("%-5d",number); } number++; } } public static boolean isPrime(int number){ for (int divisor = 2;divisor <= number / 2;divisor++){ if (number % divisor == 0){ return false; } } return true; } } - 模塊化的代碼是的代碼易于維護(hù)和調(diào)試,并且是的代碼可以被調(diào)用。
-
6.7 示例學(xué)習(xí):將十六進(jìn)制數(shù)轉(zhuǎn)換為十進(jìn)制數(shù)
package chapter06; import java.util.Scanner; public class Hex2Dec { public static void main(String[] args){ Scanner input = new Scanner(System.in); System.out.print("Enter a hex number: "); String hex = input.nextLine(); System.out.println("The decimal value for hex number " + hex + " is " + hexToDecimal(hex.toUpperCase())); } public static int hexToDecimal(String hex){ int decimalValue = 0; for (int i = 0;i < hex.length();i++){ char hexChar = hex.charAt(i); decimalValue = decimalValue * 16 + hexCharToDecimal(hexChar); } return decimalValue; } public static int hexCharToDecimal(char ch){ if (ch >= 'A' && ch <= 'F') return 10 + ch - 'A'; else return ch - '0'; } } -
6.8 重載方法
- 重載方法使得你可以使用同樣的名字來定義不同方法,只要他們的參數(shù)列表是不同的。
package chapter06; public class TestMethodOverloading { public static void main(String[] args){ System.out.println("The maximum of 3 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); } } - 重載方法可以使得程序更加清晰,以及更加具有可讀性。執(zhí)行同樣功能但是具有不同參數(shù)類型的方法應(yīng)該使用同樣的方法。
- 被重載的方法必須具有不同的參數(shù)列表。不能基于不同修飾符或返回值類型來重載方法。
- 有時調(diào)用一個方法時,會有兩個或更多可能的匹配,但是,編譯器無法判斷哪個是最精確的匹配。這稱為歧義調(diào)用。歧義調(diào)用會產(chǎn)生一個編譯錯誤。
- 重載方法使得你可以使用同樣的名字來定義不同方法,只要他們的參數(shù)列表是不同的。
-
6.9 變量的作用域
- 在方法中定義的變量稱為局部變量。局部變量的作用域是從變量聲明的地方開始,知道包含該變量的塊結(jié)束為止。局部變量都必須在使用之前進(jìn)行聲明和賦值。
- 可以在一個方法中的不同塊里聲明同名的局部變量,但是,不能再嵌套塊中或同意塊中兩次聲明同一個變量。
- 一種常見的錯誤是在for循環(huán)中國聲明一個變量,然后試圖在循環(huán)外使用它。
-
6.10 示例學(xué)習(xí):生成隨機(jī)字符
package chapter06; public class TestRandomCharacter { public static void main(String[] args){ final int NUMBER_OF_CHARS = 175; final int CHARS_PER_LINE = 25; for (int i = 0;i < NUMBER_OF_CHARS;i++){ char ch = RandomCharacter.getRandomLowerCaseLetter(); if ((i + 1) % CHARS_PER_LINE == 0) System.out.println(ch); else System.out.print(ch); } } }package chapter06; public class RandomCharacter { public static char getRandomCharacter(char ch1,char ch2){ return (char)(ch1 + Math.random() * (ch2 - ch1 + 1)); } 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'); } } -
6.11 方法抽象和逐步求精
方法抽象是通過將方法的使用和他的實(shí)現(xiàn)分離來實(shí)現(xiàn)的。
當(dāng)編寫一個程序時,可以使用“分治”策略,也稱為逐步求精,將大問題分解成小問題,子問題又分解成更小、更容易處理的問題。- 6.11.1 自頂向下的設(shè)計(jì)
- 6.11.2 自定向下和自頂向上的實(shí)現(xiàn)
- 6.11.3 實(shí)現(xiàn)細(xì)節(jié)
- 6.11.4 逐步求精的優(yōu)勢
- 1、更簡單的程序
- 2、重用方法
- 3、易于開發(fā)、調(diào)試和測試
- 4、更方便團(tuán)隊(duì)合作