1. 方法多載
方法多載(method overloading)是指:在同一個類別中,可以宣告多個同名方法,但其參數列表(型別、數量或順序)不同。當你呼叫這樣的方法時,編譯器會依你傳入的引數,自動決定要使用哪個版本。
生活中的類比
想像你在撥打銀行客服。你可以撥不同的電話號碼——個人客戶、法人客戶、VIP 客戶。號碼不同,但目的相同——獲得協助。在程式設計中,方法多載就像是一個客服號碼,能依你的問題(也就是你傳的參數)自動把你轉接到正確的客服人員。
Java 中的多載語法
在 Java 中實作方法多載很簡單:宣告多個同名方法,但參數不同。
重要規則:
多載只以參數列表(型別、數量、順序)來區分。
不能只靠回傳型別來多載!
若方法名稱與參數都相同,即使回傳型別不同,編譯器也無法區分它們。
簡單範例
public class Printer {
// 列印整數
void print(int x) {
System.out.println("int: " + x);
}
// 列印字串
void print(String s) {
System.out.println("String: " + s);
}
// 列印兩個數字
void print(int x, int y) {
System.out.println("int, int: " + x + ", " + y);
}
}
使用方式:
Printer printer = new Printer();
printer.print(42); // 會呼叫 print(int x)
printer.print("Hello!"); // 會呼叫 print(String s)
printer.print(5, 10); // 會呼叫 print(int x, int y)
編譯器會依傳入的引數,自行判定要呼叫哪個方法。
2. 編譯器如何挑選合適的方法
當你呼叫多載方法時,編譯器會分析引數列表,找出最適合的版本。
選擇準則:
- 引數數量相符。
- 每個引數的型別相符(或可以轉換,例如 int → double)。
- 若有多個方法都合適,會選擇最具特異性的那個。
範例:
public class OverloadDemo {
void show(int x) {
System.out.println("show(int): " + x);
}
void show(double x) {
System.out.println("show(double): " + x);
}
public static void main(String[] args) {
OverloadDemo demo = new OverloadDemo();
demo.show(5); // show(int): 5
demo.show(5.5); // show(double): 5.5
}
}
如果呼叫 demo.show(5),編譯器會選擇 show(int)。若以 5.5 呼叫——則會選擇 show(double)。
型別轉換
如果沒有剛好匹配的方法,編譯器會嘗試轉換引數型別(例如 int → double),但前提是可行且不會產生歧義。
void print(double x) { /* ... */ }
print(5); // int 5 會被轉為 double 5.0
僅依回傳型別多載——行不通!
許多新手會嘗試這麼做:
// 錯誤!這樣的多載是不可行的
int sum(int x, int y) { return x + y; }
double sum(int x, int y) { return (double) (x + y); }
若你只寫下 sum(2, 3),編譯器無法判定你想呼叫哪個方法。
請記住: 方法多載只能依參數來區分,不能依回傳型別!
3. 建構子多載
不只一般方法可以多載,建構子也可以!
public class Person {
String name;
int age;
// 只有名稱的建構子
public Person(String name) {
this.name = name;
this.age = 0; // 預設值
}
// 具有名稱與年齡的建構子
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
使用方式:
Person p1 = new Person("安娜");
Person p2 = new Person("波里斯", 25);
4. 實用範例
具有多載的 Calculator
我們來寫一個 Calculator 類別,能對不同型別與數量的數字進行加總。
public class Calculator {
// 兩個整數相加
int add(int a, int b) {
return a + b;
}
// 三個整數相加
int add(int a, int b, int c) {
return a + b + c;
}
// 兩個 double 相加
double add(double a, double b) {
return a + b;
}
}
使用方式:
Calculator calc = new Calculator();
System.out.println(calc.add(2, 3)); // 5
System.out.println(calc.add(1, 2, 3)); // 6
System.out.println(calc.add(2.5, 3.1)); // 5.6
標準程式庫中的方法多載
即使你沒有特別留意,其實也早就用過多載了。比方說,System.out 中的 println 就對不同型別提供多載:
System.out.println("Hello"); // println(String)
System.out.println(123); // println(int)
System.out.println(3.14); // println(double)
System.out.println(true); // println(boolean)
打開 PrintStream 的原始碼——你會看到數十個多載版本的 println。
5. 何時應該使用多載
方法多載很強大,但要審慎使用。它在以下情境特別有用:
- 方法的核心邏輯相同,但參數可能不同。
- 希望讓類別的 API 更友善、彈性更高。
- 需要同時支援舊的與新的呼叫方式。
實務中的例子:
在我們的教學應用(例如任務管理器)中,可以實作一個用於新增任務的方法,支援不同參數:
public class TaskManager {
void addTask(String description) { ... }
void addTask(String description, int priority) { ... }
void addTask(String description, int priority, String deadline) { ... }
}
這種做法不只讓使用此類別的人更方便,也讓你的類別對未來的調整更具彈性。
6. 多載與 varargs(可變參數)
在 Java 中,你可以用 ...(varargs)宣告帶有可變參數的方法:
void printAll(String... messages) {
for (String msg : messages) {
System.out.println(msg);
}
}
現在可以這樣呼叫:
printAll("Hello");
printAll("One", "Two", "Three");
也可以搭配 varargs 做多載,但要小心:如果同時存在一個使用 varargs 的方法與一個參數數量固定的方法,編譯器會先嘗試尋找「完全相符」的那個。
7. 多載常見錯誤
錯誤 №1:引數型別混淆。
如果你有方法 void process(int x) 與 void process(double x),呼叫 process(5) 會使用第一個版本,而 process(5.0)——會使用第二個。但若呼叫 process(5L),編譯器會尋找最佳匹配,可能選到不直觀的多載(甚至直接回報模稜兩可)。
錯誤 №2:搭配自動轉型的多載。
若你有 void foo(Integer x) 與 void foo(Long x),呼叫 foo(5) 會導致編譯錯誤——編譯器不知道要選哪個方法,因為 5 既可以對應為 Integer,也可以對應為 Long。
錯誤 №3:僅依回傳型別進行多載。
如前所述,只是回傳型別不同的方法,不能視為可多載。
錯誤 №4:多載與繼承。
如果在基底類別中宣告了一個方法,而你在子類別中宣告同名但不同簽章的方法,這是多載,而不是覆寫。這點很常被混淆!詳細內容——請見下一堂課。
GO TO FULL VERSION