Java 存取修飾詞 (Access Modifiers)

存取修飾詞控制類別、方法和變數的可見範圍。

四種存取修飾詞

修飾詞同類別同套件子類別其他
public
protected
(無/default)
private

public

任何地方都可以存取:

public class User {
    public String name;
    
    public void sayHello() {
        System.out.println("Hello, " + name);
    }
}

// 任何地方都可以使用
User user = new User();
user.name = "Alice";
user.sayHello();

private

只有同一類別內可以存取:

public class BankAccount {
    private double balance;  // 只有本類別可存取
    
    public BankAccount(double initialBalance) {
        this.balance = initialBalance;
    }
    
    public void deposit(double amount) {
        if (amount > 0) {
            balance += amount;  // 類別內可以存取
        }
    }
    
    public double getBalance() {
        return balance;
    }
}

BankAccount account = new BankAccount(1000);
// account.balance = 5000;  // 錯誤!private
account.deposit(500);         // OK
System.out.println(account.getBalance());  // 1500

protected

同套件和子類別可以存取:

// Animal.java
package animals;

public class Animal {
    protected String name;
    
    protected void eat() {
        System.out.println(name + " is eating");
    }
}

// Dog.java
package animals;

public class Dog extends Animal {
    public void bark() {
        System.out.println(name + " says woof!");  // OK,繼承
        eat();  // OK,繼承
    }
}

// Main.java
package app;

import animals.Dog;

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog();
        // dog.name = "Buddy";  // 錯誤!不同套件
        // dog.eat();           // 錯誤!不同套件
    }
}

default(預設/套件私有)

沒有修飾詞時,只有同套件可以存取:

// 同套件
package mypackage;

class Helper {  // default 類別
    int value;  // default 變數
    
    void doSomething() {  // default 方法
        System.out.println("Doing something");
    }
}

// 同套件可以存取
class Main {
    public static void main(String[] args) {
        Helper h = new Helper();  // OK
        h.value = 10;             // OK
        h.doSomething();          // OK
    }
}

類別的存取修飾詞

  • 頂層類別只能用 public 或 default
  • public 類別的檔案名稱必須與類別名稱相同
// MyClass.java
public class MyClass {  // public 類別
    // ...
}

class Helper {  // default 類別,同檔案
    // ...
}

實際應用

封裝

public class Person {
    private String name;
    private int age;
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        if (name != null && !name.isEmpty()) {
            this.name = name;
        }
    }
    
    public int getAge() {
        return age;
    }
    
    public void setAge(int age) {
        if (age >= 0 && age <= 150) {
            this.age = age;
        }
    }
}

工具類別

public class StringUtils {
    // 私有建構子,防止實例化
    private StringUtils() {}
    
    public static boolean isEmpty(String s) {
        return s == null || s.isEmpty();
    }
    
    // 內部使用的方法
    private static String sanitize(String s) {
        return s.trim().toLowerCase();
    }
}

選擇建議

情況建議
實例變數private(用 getter/setter)
常數public static final
內部實作細節private
API 方法public
給子類別擴展protected
套件內部使用default

最佳實踐

  1. 最小權限原則:預設使用最嚴格的存取權限
  2. 封裝內部狀態:變數使用 private
  3. 公開介面:方法依需要使用 public
  4. 保護擴展點:給子類別用的使用 protected
public class GoodDesign {
    // 私有欄位
    private int value;
    
    // 公開介面
    public int getValue() {
        return value;
    }
    
    // 給子類別的擴展點
    protected void process() {
        // ...
    }
    
    // 內部實作
    private void validate() {
        // ...
    }
}