首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 存取修飾符完整指南:public、protected、default、private 與封裝最佳實踐

     編輯:Java 相關知識

存取修飾符是 Java 封裝機制的基石,決定類別、欄位、方法、建構子對外部的可見性。本文系統整理四大修飾符規則、類別層級限制、繼承與跨包可見性矩陣、實戰案例與設計原則。

四大修飾符核心規則速查表

| 修飾符 | 類別 (頂層) | 成員 (欄位/方法/建構子) | 同類 | 同包 | 子類 (異包) | 非子類 (異包) | |--------|-------------|--------------------------|------|------|-------------|---------------| | public | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | protected | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | | default (無) | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | | private | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | > **關鍵口訣**:public 都能訪,**protected 多一個「子類」**;**default 只有「同包」**;**private 只有「自己」**。

類別層級修飾符限制

  • 頂層類別:只能 public 或 default,**不能**用 private/protected。
  • 內部類別:可用全部四種修飾符。
  • 一個 .java 檔:最多一個 public 類別,檔名必須與該類別同名。

實戰案例深度解析

案例 1:default (包私有) 實現模組內部協作

// package com.myapp.order;
class OrderValidator {          // default 類別,外部模組不可見
    boolean validate(Order o) { // default 方法
        return o.getAmount() > 0;
    }
}
public class OrderService {     // public API
    private final OrderValidator validator = new OrderValidator();
    public void placeOrder(Order o) {
        if (!validator.validate(o)) throw new IllegalArgumentException();
        // ...
    }
}

**優勢**:隱藏實作細節,測試時同包可直接驗證 OrderValidator,外部模組編譯期即報錯。

案例 2:protected 實現「模板方法模式」與子類擴充

public abstract class AbstractExporter {
    public final void export(Data data) { // final 禁止覆寫流程
        beforeExport();
        doExport(data);                  // protected 抽象方法,強制子類實作
        afterExport();
    }
    protected void beforeExport() {}     // protected 鉤子,子類可選覆寫
    protected void afterExport() {}
    protected abstract void doExport(Data data); // 核心擴充點
}

public class PdfExporter extends AbstractExporter {
    @Override protected void doExport(Data data) { /* PDF 邏輯 */ }
    @Override protected void beforeExport() { /* 初始化字體 */ }
}

**關鍵**:protected 讓子類**跨包**也能存取,同時對外部不可見,完美支援框架擴充。

案例 3:private 封裝不變量 + 建構子防禦性複製


public final class ImmutablePeriod {
    private final LocalDate start;  // private + final
    private final LocalDate end;

    public ImmutablePeriod(LocalDate start, LocalDate end) {
        // 防禦性複製:防止呼叫端持有引用竄改
        this.start = Objects.requireNonNull(start);
        this.end = Objects.requireNonNull(end);
        if (this.start.isAfter(this.end)) throw new IllegalArgumentException();
    }

    public LocalDate getStart() { return start; } // 回傳不可變物件安全
    public LocalDate getEnd() { return end; }

    // 刻意不提供 setter,保證不可變性
}

案例 4:建構子私有化實現單例 / 工廠模式


public class Singleton {
    private static final Singleton INSTANCE = new Singleton();
    private Singleton() {} // 私有建構子,禁止外部 new
    public static Singleton getInstance() { return INSTANCE; }
}

常見誤區與避坑指南

| 誤區 | 正確認知 | |------|----------| | protected = 同包 + 子類 = default + 子類 | **錯**!protected 允許**子類實例**存取 **其他子類實例** 的 protected 成員;default 不行。 | | 介面方法預設 public,不可改 | **Java 9+** 介面支援 private 方法 (內部複用)、**static** 方法、**default** 方法。 | | 內部類別 private 只能外部類存取 | **對**,但外部類**所有**內部類 (含巢狀) 皆可存取該私有內部類。 | | final 類別不可繼承,但可繼承其方法 | **錯**!final 類別完全禁止繼承,方法自然也不可覆寫。 |

封裝設計原則 (Effective Java 條款)

  1. 盡可能降低可見性:頂層類別非 public 必須 default;成員預設 private,需要時再放寬。
  2. 公開欄位必須是常量:public static final 命名全大寫底線,基本型別或不可變物件安全;可變物件 (陣列、集合) **嚴禁**公開。
  3. 用存取方法取代公開欄位:Getter/Setter 可加驗證、延遲初始化、防禦性複製、日誌審計。
  4. 模組化時代:配合 module-info.java exports/opens 進一步控制編譯期/執行期可見性。

總結

存取修飾符不是語法糖,而是**架構邊界的宣示**:

  • public = 契約 API,嚴謹設計、向相容演進。
  • protected = 框架擴充點,文檔化預期行為。
  • default = 模組內部實現,重構自由、編譯期保護。
  • private = 類別不變量核心,唯一真理來源。

內化這四層邊界,即能寫出「易維護、難誤用、可演進」的專業 Java 程式碼。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved