protected 成員對以下可見:
default)。// package pkg1
class MyObject2 {
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
// package pkg1
public class Test2 {
public static void main(String[] args) throws Exception {
MyObject2 obj = new MyObject2();
obj.clone(); // 編譯通過:同套件,protected 可見
}
}
// package pkg1
class MyObject3 {
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
// package pkg2
public class Test3 extends MyObject3 {
public static void main(String[] args) throws Exception {
MyObject3 obj = new MyObject3();
obj.clone(); // ❌ 編譯錯誤:obj 是父類別實例,非子類別實例
Test3 tobj = new Test3();
tobj.clone(); // ✅ 編譯通過:tobj 是子類別實例
}
}
Java Language Specification / Java in a Nutshell:
"Suppose class A declares a protected field x and is extended by class B in a different package. Class B inherits x, and its code can access x in the current instance of B or any other instances of B. This does NOT mean B can access x in arbitrary instances of A!"
| 錯誤認知 | 正確認知 |
|---|---|
| protected = 同套件 + 所有子類別 | protected = 同套件 + 子類別自身實例 |
| 子類別可存取父類別任何實例的 protected 成員 | 子類別僅能存取子類別型別實例的 protected 成員 |
| 覆寫後變 public 只是為了方便 | 覆寫後改 public 是為了讓任意類別可呼叫(如 clone()) |
protected 欄位,改用 private + protected getter/setter。protected 方法而非欄位。protected 的跨套件可見性限制是 Java 封裝模型精心設計的結果。理解「子類別僅能存取子類別實例的 protected 成員」是避開編譯錯誤與設計缺陷的關鍵。建議開發者養成查閱 JLS 的習慣,建立精確的語言模型。