1. 建構子多載的語法
現實中很少所有物件都用同一種方式建立。想像有個類別 Person(人)。有時我們只知道他的名字;有時知道名字和年齡;有時什麼都不知道,就讓一切用預設值。若總是強迫類別的使用者提供所有參數,即使不需要,也很奇怪。
建構子多載 是讓類別的使用者在建立物件時可以選擇:哪些參數要指定、哪些使用預設值。這讓類別更具彈性且更易於使用。
類比:
在設計汽車的部門裡,有人訂購基本款(沒有冷氣,只有方向盤與輪子),有人想要「豪華」款(座椅加熱、有 Wi‑Fi,甚至希望能自動駕駛)。但車子仍然是同一個類別,只是有不同的組裝方式!
多載指的是在 同一個類別中宣告多個建構子,但參數不同(數量、型別或順序不同)。它們都與類別同名,且沒有回傳型別。
範例:具有多個建構子的類別
public class Person {
String name;
int age;
// 無參數建構子(預設)
public Person() {
this.name = "未知";
this.age = 0;
}
// 單一參數的建構子
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(); // 名字 = "未知",年齡 = 0
Person p2 = new Person("Vasya"); // 名字 = "Vasya",年齡 = 0
Person p3 = new Person("Petya", 25); // 名字 = "Petya",年齡 = 25
Java 如何判斷要用哪個建構子?
Java 會看你在 new 之後傳入的引數數量與型別。若你寫 new Person("Vasya"),編譯器會尋找具有單一 String 參數的建構子。若你寫 new Person("Petya", 25),就需要具有 String 與 int 參數的建構子。
2. 從一個建構子呼叫另一個:this(...)
在多載建構子時,可能會有部分程式碼重複。比如你希望所有建構子一定要設定名字,而年齡若未指定就為 0。為了避免在每個建構子中複製相同邏輯,可以使用關鍵字 this(...) 從一個建構子呼叫另一個建構子。
範例
public class Person {
String name;
int age;
// 兩個參數的建構子
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 單一參數的建構子呼叫另一個建構子
public Person(String name) {
this(name, 0); // 呼叫 Person(String name, int age)
}
// 無參數建構子呼叫另一個建構子
public Person() {
this("未知", 0);
}
}
public Person(String name) {
this(name, 0); // 呼叫 Person(String, int)
}
重要規則:透過 this(...) 呼叫其他建構子必須是建構子中的第一行!
為什麼需要這樣做?
- 減少程式碼重複。
- 若你決定調整初始化邏輯(例如修改預設值),只需在一處修改。
- 程式碼更乾淨、也更易於維護。
3. 實務範例:在真實類別中的多載
假設我們有一個類別 Account — 銀行帳戶。有時只知道擁有者的名字;有時想一開始就指定初始餘額;有時還會再加上幣別。
具有多個建構子的類別範例
public class Account {
String owner;
double balance;
String currency;
// 三個參數的建構子
public Account(String owner, double balance, String currency) {
this.owner = owner;
this.balance = balance;
this.currency = currency;
}
// 兩個參數的建構子(預設幣別為 "EUR")
public Account(String owner, double balance) {
this(owner, balance, "EUR");
}
// 單一參數的建構子(餘額 = 0,幣別 = "EUR")
public Account(String owner) {
this(owner, 0.0, "EUR");
}
// 無參數建構子(擁有者為 "未知",餘額 = 0,幣別 = "EUR")
public Account() {
this("未知", 0.0, "EUR");
}
public void printInfo() {
System.out.println(owner + ": " + balance + " " + currency);
}
}
使用方式
public class Main {
public static void main(String[] args) {
Account acc1 = new Account("Ivan", 1000, "USD");
Account acc2 = new Account("Mariya", 500);
Account acc3 = new Account("Pyotr");
Account acc4 = new Account();
acc1.printInfo(); // Ivan: 1000.0 USD
acc2.printInfo(); // Mariya: 500.0 EUR
acc3.printInfo(); // Pyotr: 0.0 EUR
acc4.printInfo(); // 未知: 0.0 EUR
}
}
為什麼這樣很方便?
- 可以用不同的詳細程度來建立物件。
- 不必每次都指定所有參數(尤其當它們經常相同時)。
- 容易擴充類別:如果出現新參數,可以再新增一個建構子。
4. 建構子多載的常見錯誤
錯誤 №1:參數型別與順序的混淆。
如果你有兩個建構子 — Person(String name, int age) 與 Person(int age, String name) — 編譯器可以分辨它們,但對類別使用者而言可能非常混亂。最好避免這種情況。
錯誤 №2:缺少預設建構子。
如果你只宣告了帶參數的建構子,之後卻嘗試不帶參數建立物件——會得到編譯錯誤。若需要,務必提供無參數的建構子。
錯誤 №3:呼叫其他建構子不是在第一行。
使用 this(...) 的呼叫一律必須是建構子的第一行。若在此之前寫了其他語句——會發生編譯錯誤。
錯誤 №4:建構子呼叫造成循環。
如果建構子直接或透過鏈結間接呼叫到自己,會因為無窮遞迴而導致編譯錯誤。
錯誤 №5:欄位未初始化。
如果忘了在建構子(或呼叫鏈)中初始化某個欄位,物件可能會處於不正確的狀態。請確認所有欄位在物件建立後都有合理的值。
GO TO FULL VERSION