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

Java protected 訪問控制深度解析:子類跨包訪問的隱形邊界

     編輯:Java 相關知識

一個反直覺的現象


// 包 A
package testa;
public class Animal {
    protected void crowl(String c) { System.out.println(c); }
}

// 包 B
package testb;
import testa.Animal;

class Cat extends Animal { }

class Rat extends Animal {
    public void crowl() {
        crowl("zhi zhi");           // ✅ 編譯通過:訪問自己繼承的 protected 方法
        Cat cat = new Cat();
        cat.crowl("miao miao");     // ❌ 編譯錯誤:The method crowl(String) from the type Animal is not visible
    }
}

同為 Animal 的子類,為什麼 Rat 內部能調用自己的 crowl(),卻不能調用 Cat 繼承的 crowl()?

核心規則:protected 的「同包 + 子類」與「子類內部」邊界

protected 成員對「同包類」和「所有子類」可見。但子類只能在「自己的作用域內」訪問「自己繼承」的 protected 成員,不能訪問「兄弟類實例」繼承的 protected 成員。

圖解訪問權限矩陣

訪問位置同包類不同包子類(自身繼承)不同包子類(兄弟實例)不同包非子類
public✅✅✅✅
protected✅✅❌❌
default✅❌❌❌
private❌❌❌❌

深度解析:為什麼設計成這樣?

  1. 封裝性: 子類繼承父類 protected 成員是為了「自己用」(擴展功能),不是為了「給兄弟用」。允許跨實例訪問會破壞封裝,導致耦合失控。
  2. 繼承契約: Cat 繼承的 crowl() 是 Cat 的實現細節,Rat 無權干涉。
  3. 克隆陷阱關聯: 這就是為什麼 clone() 是 protected,且無法直接 obj.clone()——因為你只能克隆「自己」,不能克隆「別人」。

實戰啟示

  • 設計 API 時,protected 方法預期只被子類內部調用,不要指望其他同包類或兄弟類實例調用。
  • 若需暴露給同包或其他類使用,請提升為 public 或提供 public 門面方法。
  • 跨包子類之間共享邏輯,應放在父類 protected 方法中,各子類各自調用自己的繼承版本,而非互相調用。

總結

protected 不是「包內公有、子類公有」那麼簡單。它的真實含義是:包內可見 + 子類內部可見(僅限自身繼承副本)。牢記這條「隱形邊界」,能幫你避開繼承體系中最隱蔽的訪問控制陷阱。

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