Java 封裝的核心在於**訪問權限控制**。本文通過一個**跨包、繼承、同類**的完整測試矩陣,系統對比 public、protected、default (package-private)、private 四大修飾符對**成員變數**與**成員方法**的可見性差異,附完整可編譯測試代碼與「誰能訪問誰」速查表,徹底解決權限困惑。
Base 定義四種權限的變數 i1~i4 與方法 m1()~m4()。SubSamePkg extends Base。OtherSamePkg。SubDiffPkg extends Base (在 other.pkg)。OtherDiffPkg (在 other.pkg)。
// 檔案:AccessTest.java
package access;
public class Base {
public int i1 = 1; int i2 = 2; protected int i3 = 3; private int i4 = 4;
public void m1() {} void m2() {} protected void m3() {} private void m4() {}
}
class SubSamePkg extends Base {
void test() {
System.out.println(i1); System.out.println(i2); System.out.println(i3); // System.out.println(i4); // 編譯錯誤
m1(); m2(); m3(); // m4(); // 編譯錯誤
}
}
class OtherSamePkg {
void test(Base b) {
System.out.println(b.i1); System.out.println(b.i2); System.out.println(b.i3); // b.i4 錯誤
b.m1(); b.m2(); b.m3(); // b.m4() 錯誤
}
}
// 異包類需放在 other/pkg 目錄下,此處模擬說明
/*
package other.pkg;
import access.Base;
public class SubDiffPkg extends Base {
void test() {
System.out.println(i1); // System.out.println(i2); // default 不可見
System.out.println(i3); // System.out.println(i4); // private 不可見
m1(); // m2(); // default 不可見
m3(); // m4(); // private 不可見
}
}
public class OtherDiffPkg {
void test(Base b) {
System.out.println(b.i1); // b.i2 錯誤, b.i3 錯誤, b.i4 錯誤
b.m1(); // b.m2() 錯誤, b.m3() 錯誤, b.m4() 錯誤
}
}
*/
public class AccessTest {
public static void main(String[] args) {
Base b = new Base();
System.out.println("=== 同包非子類訪問 Base 實例 ===");
System.out.println(b.i1); System.out.println(b.i2); System.out.println(b.i3); // b.i4 不可見
b.m1(); b.m2(); b.m3(); // b.m4() 不可見
System.out.println("\n=== 同包子類內部訪問繼承成員 ===");
new SubSamePkg().test();
System.out.println("\n=== 異包子類/非子類:請移至 other.pkg 執行 ===");
}
}
| 修飾符 | 同類 | 同包子類 | 同包非子類 | 異包子類 | 異包非子類 |
|---|---|---|---|---|---|
public | ✅ | ✅ | ✅ | ✅ | ✅ |
protected | ✅ | ✅ | ✅ | ✅ (繼承) | ❌ |
default | ✅ | ✅ | ✅ | ❌ | ❌ |
private | ✅ | ❌ | ❌ | ❌ | ❌ |
parent.protectedField。public abstract;Java 9+ 允許 private 靜態/實例方法。public 或 default;內部類可用四種修飾符。super()。private**,提供 public/protected Getter/Setter(封裝)。private**,需要時再放寬至 protected (供子類擴展) 或 public (對外 API)。default 實現包級協作,減少 public 暴露面。public 欄位)。熟練掌握四大權限修飾符的邊界,是寫出高內聚、低耦合、安全可控 Java 代碼的基石。