1. 何謂方法
-
Java 方法是語句的集合得滤,它們在一起執(zhí)行一個功能。
- 方法是解決一類問題的步驟的有序組合爪膊;
- 方法包含于類或?qū)ο笾校?/li>
- 方法在程序中被創(chuàng)建,在其他地方被引用砸王。
-
設(shè)計方法的原則:方法的本意是功能塊推盛,就是實現(xiàn)某個功能的語句塊的集合。我們設(shè)計方法的時候谦铃,最好保持方法的原子性耘成,就是 一個方法只完成 1 個功能,這樣利于我們后期的擴展驹闰。
package github.method; public class Demo01 { // main方法 public static void main(String[] args) { int sum = add(1, 2); System.out.println(sum); } // 加法 public static int add(int a,int b){ return a+b; } }
2. 方法的定義及調(diào)用
Java 的方法類似于其它語言的函數(shù)瘪菌,是一段用來完成特定功能的代碼片段,一般情況下嘹朗,定義一個方法包含以下語法:
-
方法包含一個方法頭和一個方法體师妙。下面是一個方法的所有部分:
修飾符:是可選的,告訴編譯器如何調(diào)用該方法屹培。定義了該方法的訪問類型默穴。
返回值類型:方法可能會返回值。 returnValueType 是方法返回值的數(shù)據(jù)類型褪秀。有些方法執(zhí)行所需的操作壁顶,但沒有返回值。在這種情況下溜歪, returnValueType 是關(guān)鍵字 void若专。
方法名:是方法的實際名稱。方法名和參數(shù)表共同構(gòu)成方法簽名蝴猪。(首字母小寫调衰,駝峰命名)
-
參數(shù)類型:參數(shù)像是一個占位符膊爪。當(dāng)方法被調(diào)用時,傳遞值給參數(shù)嚎莉。這個值被稱為實參或變量米酬。參數(shù)列表是指方法的參數(shù)類型、順序和參數(shù)的個數(shù)趋箩。參數(shù)是可選的赃额,方法可以不包含任何參數(shù)。
- 形式參數(shù):在方法被調(diào)用時用于接收外界輸入的數(shù)據(jù)叫确。
- 實參:調(diào)用方法時實際傳給方法的數(shù)據(jù)跳芳。
方法體:方法體包含具體的語句,定義該方法的功能竹勉。
修飾符 返回值類型 方法名(參數(shù)類型 參數(shù)名){ ... 方法體 ... return 返回值; }
調(diào)用方法:對象名.方法名(實參列表)
-
Java 支持兩種調(diào)用方法的方式飞盆,根據(jù)方法是否返回值來選擇,當(dāng)方法返回一個值的時候次乓,方法調(diào)用通常被當(dāng)做一個值吓歇。例如:
int larger = max(30,40);
-
如果方法返回值是 void ,方法調(diào)用一定是一條語句票腰。
System.out.println("Hello,World!");
-
示例:
package github.method; public class Demo02 { public static void main(String[] args) { int max = max(10, 20); System.out.println(max); } // 比大小 public static int max(int num1,int num2){ int result = 0; if(num1==num2){ System.out.println("num1==num2"); return 0; // 終止方法 } if(num1>num2){ result = num1; } else { result = num2; } return result; } }
值傳遞 (Java)和引用傳遞
- 方法可以修改 傳遞引用所對應(yīng)的 變量值城看,而 不能修改傳遞值調(diào)用 所對應(yīng)的變量值,這句話相當(dāng)重要杏慰,這是按值調(diào)用與引用調(diào)用的根本區(qū)別析命,以下為分析:
- 按值調(diào)用 (call by value) 表示方法接受的時調(diào)用者 提供的值。
package github.method; public class Demo03 { private static int x = 10; public static void updateValue(int value) { value = 3 * value; System.out.println("value的值:" + value); } public static void main(String[] args) { System.out.println("調(diào)用前的值:" + x); updateValue(x); System.out.println("調(diào)用后的值:" + x); } }
分析:
value 被初始化逃默,為 x 值的一個拷貝(也就是10)
value 被乘以 3 后等于30鹃愤,但注意此時 x 的值仍為10!
這個方法結(jié)束后完域,參數(shù)變量 value 不再使用软吐,被回收。
結(jié)論:當(dāng)傳遞方法參數(shù)類型為基本數(shù)據(jù)類型(數(shù)字以及布爾值)時吟税,一個方法是不可能修改一個基本數(shù)據(jù)類型的參數(shù)凹耙。
按引用調(diào)用 (call by reference)
按引用調(diào)用,則表示方法接收的是 調(diào)用者提供的變量地址 (如果是 C 語言肠仪,就是指針肖抱,Java 并沒有指針的概念)
-
當(dāng)然 Java 中除了 基本數(shù)據(jù)類型,還有 引用數(shù)據(jù)類型异旧,也就是 對象引用意述,那么對于這種數(shù)據(jù)類型又是怎么樣的情況呢?我們還是一樣先來看一個例子:
- 先聲明一個 User 對象類型:
package github.method; public class User { private String name; private int age; public User(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
- 執(zhí)行 class
package github.method; public class Test02 { public static void updateUser(User student) { student.setName("Liu"); student.setAge(22); } public static void main(String[] args) { User user = new User("USER", 20); System.out.println("調(diào)用user前的值:" + user.getName() + "," + user.getAge()); updateUser(user); System.out.println("調(diào)用user后的值:" + user.getName() + "," + user.getAge()); } }
分析一下這個過程:
分析:
- student 變量被初始化為 user 值的拷貝,這里是一個對象的引用荤崇。
- 調(diào)用 student 變量的 set 方法作用在這個引用對象上拌屏,user 和 student 同時引用的 User 對象內(nèi)部值 被修改。
- 方法結(jié)束后术荤,student 變量不再使用倚喂,被釋放,而 user 還是沒有變瓣戚,依然指向User 對象端圈。
結(jié)論:顯然,User 的值被改變了子库,但是這是將最開始所對應(yīng)得值改變了舱权,把 User 的本身屬性改變了,才會進(jìn)行值得變化刚照,雖然看似是按引用傳遞值,但是實際上是將值改變了喧兄。
- 下面通過一個反例來說明:
package github.method; /** * java 中的按值調(diào)用 */ public class Test03 { /** * 交換兩個對象 * * @param x * @param y */ public static void swap(User x, User y) { User temp = x; x = y; y = temp; } public static void main(String[] args) { User user = new User("user", 26); User stu = new User("stu", 18); System.out.println("調(diào)用前user的值:" + user.getName() + "," + user.getAge()); System.out.println("調(diào)用前stu的值:" + stu.getName() + "," + stu.getAge()); swap(user, stu); System.out.println("調(diào)用后user的值:" + user.getName() + "," + user.getAge()); System.out.println("調(diào)用后stu的值:" + stu.getName() + "," + stu.getAge()); } }
-
通過程序發(fā)現(xiàn):user 和 stu 的值并沒有發(fā)生變化无畔,也就是方法并沒有改變存儲在變量 user 和 stu 中的對象引用。swap 方法的參數(shù) x 和 y 被初始化為兩個對象引用的拷貝吠冤,這個方法交換的是這兩個拷貝的值而已浑彰,最終,所做的事都是白費力氣罷了拯辙。在方法結(jié)束后 x郭变,y 將被丟棄,而原來的變量 user 和 stu 仍然引用這個方法調(diào)用之前所引用的對象涯保。
-
這個過程也充分說明了诉濒,Java 程序設(shè)計語言對
對象
采用的不是引用調(diào)用,實際上是 對象引用進(jìn)行的是值傳遞夕春,當(dāng)然在這里我們可以簡單理解為這就是按值調(diào)用和引用調(diào)用的區(qū)別未荒,而且必須明白即使 Java 函數(shù)在傳遞引用數(shù)據(jù)類型時,也只是拷貝了引用的值罷了及志,之所以能修改引用數(shù)據(jù)是因為它們同時指向了一個對象片排,但這仍然是按值調(diào)用而不是引用調(diào)用。總結(jié)
一個方法不能修改一個基本數(shù)據(jù)類型的參數(shù)(數(shù)值型和布爾型)速侈。
一個方法可以修改一個引用所指向的對象狀態(tài)率寡,但這仍然是按值調(diào)用而非引用調(diào)用。
上面兩種傳遞都進(jìn)行了值拷貝的過程倚搬。
3. 方法重載
重載就是在一個類中冶共,有相同的函數(shù)名稱,但形參不同的函數(shù)。
-
方法的重載的規(guī)則
- 方法名稱必須相同比默。
- 參數(shù)列表必須不同(個數(shù)不同幻捏、或類型不同、參數(shù)排列順序不同等)
- 方法的返回類型可以相同也可以不相同命咐。
- 僅僅返回類型不同篡九,不足以成為方法的重載。
-
實現(xiàn)理論:
- 方法名稱相同時醋奠,編譯器會根據(jù)調(diào)用方法的參數(shù)個數(shù)榛臼、參數(shù)類型等去逐個匹配,以選擇對應(yīng)的方法窜司,如果匹配失敗沛善,則編譯器報錯。
package github.method; public class Demo02 { public static void main(String[] args) { int max = max(10, 20); System.out.println(max); double max2 = max(10.0, 20.0); System.out.println(max2); } // 比大小 public static int max(int num1, int num2) { int result = 0; if (num1 == num2) { System.out.println("num1==num2"); return 0; // 終止方法 } if (num1 > num2) { result = num1; } else { result = num2; } return result; } // 比大小 方法重載塞祈,參數(shù)類型不同 public static double max(double num1, double num2) { double result = 0; if (num1 == num2) { System.out.println("num1==num2"); return 0; // 終止方法 } if (num1 > num2) { result = num1; } else { result = num2; } return result; } }
package github.method; public class Demo01 { // main方法 public static void main(String[] args) { int sum = add(1, 2); System.out.println(sum); int sum2 = add(1, 2, 3); System.out.println(sum2); } // 加法 public static int add(int a,int b){ return a+b; } // 方法重載金刁,參數(shù)個數(shù)不同 public static int add(int a,int b,int c){ return a+b+c; } }
4. 命令行傳參
package github.method;
public class Demo03 {
public static void main(String[] args) {
// args.length 數(shù)組長度
for(int i=0;i < args.length;i++){
System.out.println("args[" + i + "]:" + args[i]);
}
}
}
5. 可變參數(shù)
- JDK 1.5 開始,Java 支持傳遞同類型的可變參數(shù)給一個方法议薪。
- 在方法聲明中尤蛮,在指定參數(shù)類型后加一個省略號(...)。
- 一個方法中只能指定一個可變參數(shù)斯议,它必須是方法的最后一個參數(shù)产捞。任何普通的參數(shù)必須在它之前聲明。
package github.method;
public class Demo04 {
public static void main(String[] args) {
Demo04 demo04 = new Demo04(); // 另一種調(diào)用方式:對象
demo04.test(1,2,3,4,5);
}
public void test(int... i){
System.out.println(i[0]);
System.out.println(i[1]);
System.out.println(i[2]);
System.out.println(i[3]);
System.out.println(i[4]);
}
}
package github.method;
public class Demo05 {
public static void main(String[] args) {
// 調(diào)用可變參數(shù)的方法
printMax(34,3,3,2,56.5);
printMax(new double[]{1,2,3});
}
public static void printMax(double... numbers){
// 判斷是否有參數(shù)傳入
if(numbers.length==0){
System.out.println("沒有數(shù)據(jù)哼御!");
return;
}
double result = numbers[0];
// 排序
for(int i=1;i<numbers.length;i++){
if(numbers[i] > result){
result = numbers[i];
}
}
System.out.println("The max Value is " + result);
}
}
6. 遞歸
A 方法調(diào)用 B 方法坯临,我們很容易理解!
遞歸就是:A 方法調(diào)用 A 方法恋昼!就是自己調(diào)用自己看靠。
利用遞歸可以用簡單的程序來解決一些復(fù)雜的問題。它通常把一個大型復(fù)雜的問題層層轉(zhuǎn)化為一個與原問題相似的規(guī)模較小的問題來求解液肌,遞歸策略只需少量的程序就可描述岀解題過程所需要的多次重復(fù)計算衷笋,大大地減少了程序的代碼量。遞歸的能力在于用有限的語句來定義對象的無限集合矩屁。
-
遞歸結(jié)構(gòu)包括兩個部分:
- 遞歸頭:什么時候不調(diào)用自身方法辟宗。如果沒有頭,將陷入死循環(huán)吝秕;
- 遞歸體:什么時候需要調(diào)用自身方法泊脐。
package github.method; import java.util.Scanner; public class Demo05 { // 5! 5*4*3*2*1 public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println("請輸入一個數(shù):"); int number = scanner.nextInt(); int test = test(number); System.out.println(number + "的階乘:" + test); scanner.close(); } public static int test(int n){ if(n==1){ return 1; }else{ return n*test(n-1); } } }
-
寫一個計算器,要求實現(xiàn)加減乘除功能烁峭,井且能夠循環(huán)接收新的數(shù)據(jù)容客,通過用戶交互實現(xiàn)秕铛。
package github.method; import java.util.Scanner; public class Demo06 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); double sum = 0; while (true) { System.out.println("請輸入第一個整數(shù):"); double a = scanner.nextDouble(); System.out.println("請輸入第二個整數(shù):"); double b = scanner.nextDouble(); System.out.println("請輸入要運算的字符(+:表示加法,-:表示減法,*:表示乘法,/:表示除法)"); String temp = scanner.next(); switch (temp) { case "+": sum = a + b; System.out.println("結(jié)果是:" + sum); continue; case "-": sum = a - b; System.out.println("結(jié)果是:" + sum); continue; case "*": sum = a * b; System.out.println("結(jié)果是:" + sum); continue; case "/": sum = a / b; System.out.println("結(jié)果是:" + sum); continue; default: System.out.println("請輸入正確的運算符號!缩挑!"); } } } }