// 包 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 成員。
| 訪問位置 | 同包類 | 不同包子類(自身繼承) | 不同包子類(兄弟實例) | 不同包非子類 |
|---|---|---|---|---|
| public | ✅ | ✅ | ✅ | ✅ |
| protected | ✅ | ✅ | ❌ | ❌ |
| default | ✅ | ❌ | ❌ | ❌ |
| private | ❌ | ❌ | ❌ | ❌ |
Cat 繼承的 crowl() 是 Cat 的實現細節,Rat 無權干涉。clone() 是 protected,且無法直接 obj.clone()——因為你只能克隆「自己」,不能克隆「別人」。public 或提供 public 門面方法。protected 方法中,各子類各自調用自己的繼承版本,而非互相調用。protected 不是「包內公有、子類公有」那麼簡單。它的真實含義是:包內可見 + 子類內部可見(僅限自身繼承副本)。牢記這條「隱形邊界」,能幫你避開繼承體系中最隱蔽的訪問控制陷阱。