Java 學會封裝就靠這篇:訪問修飾詞完整解析(含設計模式範例)【Thinking in Java筆記(5-2)】
在物件導向程式設計中,封裝(Encapsulation) 是一個超級核心概念。透過封裝,我們可以把資料和方法包裝進類別裡,並對外「藏好」內部實作細節。這樣不僅保護了資料,也避免外部程式碼亂入亂搞
Java 提供了幾種訪問權限修飾詞,讓我們可以精確控制類別和成員的可見性,進而提升程式碼的安全性與可維護性
訪問權限控制與封裝
訪問權限的控制常被稱為具體實作的隱藏。這部分就像設定你家門的鎖,有些房間大家都能進,有些只有自己能進,還有些只能讓特定朋友進
控制範圍的設定
- 設定權限邊界:將存取控制設定在類別內部,確保只有被允許的部分對外可見
- 分離介面與實作:客戶端(也就是使用你程式碼的其他開發者)只能透過你開放的介面互動,不會碰到你程式的內臟
想像一台咖啡機:你只按按鈕,它就泡咖啡,至於裡面怎麼加熱水、怎麼磨豆,不重要也不該知道
建議的成員排序方式
為了讓閱讀更流暢,建議使用以下排序方式來定義類別中的方法與變數:
public class OrganizedByAccess {
// Public methods - 對外開放的
public void pub1() { /* ... */ }
public void pub2() { /* ... */ }
public void pub3() { /* ... */ }
// Protected methods - 給繼承用的
protected void prot1() { /* ... */ }
// Package-private methods (no modifier) - 沒有寫修飾詞的
void pack1() { /* ... */ }
// Private methods - 只在自己家裡用
private void priv1() { /* ... */ }
private void priv2() { /* ... */ }
private void priv3() { /* ... */ }
// Private fields - 私人變數
private int i;
// ...
}
這樣從上往下看,使用者會先看到對他們最有用的部分,不會一開始就看到不相關的內部程式邏輯
類別的訪問權限設定
類別能設的權限有哪些?
在 Java 中,類別本身的訪問權限只允許:
public
:大家都能用- 預設(什麼都不寫):只有同一個 package 裡的類別能用
在 Java 中,訪問權限修飾詞不僅可以應用於類別的成員,也可以用來控制整個類別的可見性
要控制某個類別的訪問權限,修飾詞需放在 class
關鍵字之前
範例:公開類別 Widget
package access;
public class Widget {}
使用者可以這樣使用:
import access.Widget;
// 或簡單一點:
import access.*;
- 一個檔案只能有一個
public
類別 public
類別名稱要和檔案名稱一模一樣(大小寫也要對!)- 如果沒有
public
類別,檔案名稱就可以比較自由一點
範例: 使用 private 建構子的類別
在開始看這段範例之前,先補充一個很容易踩到的雷:類別不能被宣告為 private
或 protected
,除非它是內部類別(nested class)
這是 Java 的語言規則,目的是避免你把整個類別藏起來讓誰都不能用。如果你真的需要那種行為,那請把它寫在另一個類別裡當作「內部秘密武器」
class Soup1 {
private Soup1() {}
// (1) Allow creation via static method:
public static Soup1 makeSoup() {
return new Soup1();
}
}
class Soup2 {
private Soup2() {}
// (2) Create a static object and return a reference
// upon request.(The "Singleton" pattern):
private static Soup2 ps1 = new Soup2();
public static Soup2 access() {
return ps1;
}
public void f() {}
}
// Only one public class allowed per file:
public class Lunch {
void testPrivate() {
// Can't do this! Private constructor:
//! Soup1 soup = new Soup1();
}
void testStatic() {
Soup1 soup = Soup1.makeSoup();
}
void testSingleton() {
Soup2.access().f();
}
}
小知識:這邊用了兩種技巧(以及為什麼你應該在乎)
對很多初學者來說,什麼「工廠模式」、「單例模式」聽起來都像是大公司開會才會講的 buzzword。但其實它們背後都是很實際的做法,是你寫久了就會發現:「啊,這樣真的比較不容易出錯」
我們這邊看到的兩種設計技巧,都是為了讓物件建立的過程變得更安全、更有控制性:
- Soup1:用靜態方法
makeSoup()
來幫忙建構實例。這就是傳說中的工廠方法模式(Factory Method Pattern)。想像你要喝湯,但不能自己煮,要請「湯工廠」幫你煮一碗給你。你不能 new,只能按鈕叫出來,這樣可以控管建構流程,也方便之後改邏輯 - Soup2:用 Singleton(單例模式)保證只會有一個實例。這像是你整個應用程式裡只有一個指揮中心,負責管理湯的供應。你不希望每次叫湯都蓋一個新湯廠,只想用同一間湯工廠處理所有需求。這種模式常見於日誌記錄器、設定管理器、資料庫連線等等
這些技巧的核心概念是:你不能隨便 new,必須透過我定義好的方式來獲得物件。這樣做可以避免錯誤使用、增加可維護性、並且讓你未來要改建構邏輯時,不會影響所有使用者的程式碼
預設(package-private)訪問權限
如果你什麼修飾詞都不寫,那就是 package-private
這是 Java 預設的類別與成員的訪問權限,意思是同一個 package 裡的類別可以看見、使用這個類別或方法,但其他 package 就看不到了
初學者很容易忽略這一點,因為不像 public
或 private
一樣明顯地寫出來。但是這種預設值在實際開發中常常是有意義的:
例如你在設計一組工具類別,這些工具只會在這個 package 裡面用到,根本不需要對外開放。這時候就不用特別寫修飾詞,讓它維持 package-private 就好
這有點像是公司裡的內部備忘錄,你的部門能看,其他部門不要來亂看。這樣做的好處是可以避免被外部誤用,讓程式碼更有界線感
就算你的類別是 package-private,它的public static
方法還是可以被叫到,只是沒辦法new
它的實體
小結
學會使用 Java 的訪問權限修飾詞,不只是寫出能跑的程式,而是寫出「預期別人會讀、會維護、會合作開發」的程式碼。這些權限設定看起來像語法細節,但實際上就是你為自己的程式碼架起防火牆、設下邊界
當你寫 private
,你是在說:「這東西我自己用就好,別碰」 當你寫 public
,你是在說:「這是我對外的保證,你可以放心使用」 而預設的 package-private
,就是說:「你是我同一組的,那就給你看一點內部機密」
懂得這些設定不只是技術層面,也代表你開始理解「軟體設計」背後的思維:誰應該知道什麼?誰不該干涉什麼?你的程式不只要能跑,還要能合作、能擴充、能被信任
所以下次你寫一個類別或方法前,先想一下:「這個別人真的需要看到嗎?」如果答案是「不」,那就勇敢地加上 private
。因為會藏東西的程式,才是長久之計
Comments ()