CodeGym /課程 /JAVA 25 SELF /建構子多載

建構子多載

JAVA 25 SELF
等級 14 , 課堂 4
開放

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),就需要具有 Stringint 參數的建構子。

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(...) 從一個建構子呼叫另一個建構子

重要規則:透過 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:欄位未初始化。
如果忘了在建構子(或呼叫鏈)中初始化某個欄位,物件可能會處於不正確的狀態。請確認所有欄位在物件建立後都有合理的值。

留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION