修飾符分類總覽
Java 修飾符用於定義類、方法、變數的語義特性,分為兩大類:
- 訪問修飾符:控制可見範圍
- 非訪問修飾符:提供額外語義(靜態、最終、抽象、同步等)
一、訪問控制修飾符(四種權限)
| 修飾符 | 關鍵字 | 同一類 | 同一包 | 子類(不同包) | 所有類 |
| public | public | ✓ | ✓ | ✓ | ✓ |
| protected | protected | ✓ | ✓ | ✓ | ✗ |
| default (package-private) | 無 | ✓ | ✓ | ✗ | ✗ |
| private | private | ✓ | ✗ | ✗ | ✗ |
1. default(包私有)——無關鍵字
String version = "1.5.1";
boolean processOrder() { return true; }
同一包內類可見。介面成員隱式 public static final,方法隱式 public。
2. private——最嚴格封裝
public class Logger {
private String format;
public String getFormat() { return format; }
public void setFormat(String format) { this.format = format; }
}
- 類/介面不能用
private
- 核心用途:隱藏實現細節、保護資料不變性
- 外部只能透過公共 getter/setter 存取
3. public——完全公開
public static void main(String[] args) { ... }
- 類、方法、建構子、介面皆可用
- 跨包使用需
import
main 必須 public,否則 JVM 無法啟動
4. protected——包內 + 子類可見
class AudioPlayer {
protected boolean openSpeaker(Speaker sp) { ... }
}
class StreamingAudioPlayer extends AudioPlayer {
@Override
public boolean openSpeaker(Speaker sp) { ... } // 可擴大為 public
}
- 不能修飾類/介面
- 介面成員不能用
protected
- 設計意圖:允許子類擴充,但隱藏給無關類
繼承與訪問權限鐵律
- 父類
public 方法 → 子類必須 public
- 父類
protected 方法 → 子類只能 protected 或 public
- 父類
private 方法 → 不可繼承(子類不可見)
二、非訪問修飾符
static——類級別成員
- 靜態變數:類變數,全類共享唯一副本,
ClassName.var 存取
- 靜態方法:不依賴實例,不能直接存取非靜態成員,
ClassName.method() 調用
public class InstanceCounter {
private static int count = 0;
public static int getCount() { return count; }
private InstanceCounter() { count++; }
}
final——不可變語義
| 修飾對象 | 效果 |
| 類 | 不可被繼承(如 String、Integer) |
| 方法 | 不可被覆寫(但可被繼承) |
| 變數 | 基本類型:值不可改;引用類型:引用不可換(但物件內容可改) |
public static final int MAX_SIZE = 100; // 常量慣例:全大寫+底線
final List list = new ArrayList<>();
list.add("OK"); // 允許:修改物件內容
// list = new ArrayList<>(); // 編譯錯誤:不可換引用
abstract——抽象契約
- 抽象類:不能實例化,可含抽象/具體方法,
abstract class
- 抽象方法:無方法體,以分號結束,子類必須實作(除非子類也是抽象類)
- 一個類含抽象方法 → 必須宣告為抽象類
abstract 與 final 互斥
synchronized——線程同步
public synchronized void threadSafeMethod() { ... }
- 同一時間僅一線程可執行
- 可與四種訪問修飾符組合
- 鎖對象:實例方法鎖
this,靜態方法鎖 Class.class
volatile——可見性保證
- 強制從主記憶體讀寫,禁止線程本地快取
- 適用於狀態標記(如
volatile boolean running = true;)
- 不保證原子性(
count++ 仍需同步或原子類)
transient——序列化排除
public transient int tempData; // 序列化時跳過,反序列化為預設值
修飾符組合速查表
| 組合 | 合法性 | 說明 |
public static final | ✓ | 全域常量標準寫法 |
private abstract | ✗ | 抽象方法需被子類實作,不能私有 |
static abstract | ✗ | 靜態方法屬於類,無法被覆寫實作 |
final abstract | ✗ | final 禁止覆寫,abstract 強制覆寫,互斥 |
synchronized static | ✓ | 鎖 Class 物件 |
最佳實踐建議
- **最小權限原則**:預設
private,需要時再放寬
- **常量規範**:
public static final UPPER_SNAKE_CASE
- **介面設計**:方法預設
public abstract,Java 8+ 可用 default/static 方法
- **線程安全**:優先用
java.util.concurrent 高階工具,減少手動 synchronized/volatile
- **文檔化**:公開 API 必加 Javadoc,說明副作用、線程安全性、異常拋出