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