Java 建構子 (Constructor)
建構子是在建立物件時自動執行的特殊方法,用來初始化物件。
基本語法
建構子的特點:
- 名稱與類別相同
- 沒有回傳型別(連 void 都沒有)
public class Person {
private String name;
private int age;
// 建構子
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
// 使用
Person p = new Person("Alice", 25);
預設建構子
如果沒有定義任何建構子,Java 會自動提供一個無參數的預設建構子:
public class Dog {
String name;
// Java 自動提供預設建構子
}
Dog d = new Dog(); // 使用預設建構子
但是,一旦定義了建構子,就不會有預設建構子:
public class Dog {
String name;
public Dog(String name) {
this.name = name;
}
}
// Dog d = new Dog(); // 錯誤!沒有無參數建構子
Dog d = new Dog("Buddy"); // OK
建構子多載
可以定義多個建構子:
public class Person {
private String name;
private int age;
// 無參數建構子
public Person() {
this.name = "Unknown";
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(); // Unknown, 0
Person p2 = new Person("Alice"); // Alice, 0
Person p3 = new Person("Bob", 25); // Bob, 25
this() 呼叫其他建構子
使用 this() 可以呼叫同一類別的其他建構子:
public class Person {
private String name;
private int age;
public Person() {
this("Unknown", 0); // 呼叫完整參數的建構子
}
public Person(String name) {
this(name, 0); // 呼叫完整參數的建構子
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
this() 必須是建構子的第一個敘述。初始化順序
public class Example {
private int a = 1; // 1. 實例變數初始化
{
// 2. 實例初始化區塊
System.out.println("初始化區塊");
}
public Example() {
// 3. 建構子
System.out.println("建構子");
}
}
私有建構子
私有建構子可以防止外部建立物件,常用於單例模式:
public class Singleton {
private static Singleton instance;
// 私有建構子
private Singleton() { }
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
// Singleton s = new Singleton(); // 錯誤!
Singleton s = Singleton.getInstance(); // OK
複製建構子
建立新物件時複製另一個物件的值:
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 複製建構子
public Person(Person other) {
this.name = other.name;
this.age = other.age;
}
}
Person original = new Person("Alice", 25);
Person copy = new Person(original); // 複製
建構子與繼承
子類別建構子會先呼叫父類別建構子:
public class Animal {
String name;
public Animal(String name) {
this.name = name;
System.out.println("Animal 建構子");
}
}
public class Dog extends Animal {
String breed;
public Dog(String name, String breed) {
super(name); // 呼叫父類別建構子
this.breed = breed;
System.out.println("Dog 建構子");
}
}
Dog d = new Dog("Buddy", "Golden");
// 輸出:
// Animal 建構子
// Dog 建構子
最佳實踐
- 初始化所有欄位:確保物件建立後處於有效狀態
- 驗證參數:在建構子中驗證輸入
- 避免太多參數:考慮使用 Builder 模式
public class User {
private final String name;
private final String email;
public User(String name, String email) {
// 驗證參數
if (name == null || name.isEmpty()) {
throw new IllegalArgumentException("名稱不能為空");
}
if (email == null || !email.contains("@")) {
throw new IllegalArgumentException("無效的 email");
}
this.name = name;
this.email = email;
}
}