protected 允许跨包子类在自身内部直接访问父类成员,但禁止通过父类引用访问;正确做法是子类继承后在方法中直接使用,错误做法是用父类变量引用子类对象再访问。

核心结论:如果你希望子类在不同包中安全使用父类的关键字段或方法,不能依赖“跨包直接调用父类实例的 protected 成员”,而应通过以下合规方式实现:
✅ 正确做法:子类继承后,在子类内部自然访问
只要子类继承了父类(即使跨包),它就可以在自己的方法中直接使用 `protected` 的字段或方法,无需额外修饰或导出。- 父类(如
com.example.core.DataProcessor)中声明:protected String secretKey = "default-key";protected void validate() { ... } - 子类(如
com.example.extended.MyProcessor)中可直接使用:@Overridepublic void process() {
System.out.println(secretKey); // ✅ 合法
validate(); // ✅ 合法}
❌ 常见错误:试图通过父类引用访问 protected 成员
即使子类和父类是继承关系,若用父类类型变量引用子类对象,也不能访问其 `protected` 成员(编译报错)。DataProcessor p = new MyProcessor();p.secretKey; // ❌ 编译失败:secretKey has protected access in DataProcessor- 原因:访问权限检查基于**变量声明类型**(
DataProcessor),而非实际运行时类型。
? 替代方案:当需要跨包共享核心资产时
如果设计上确实要求外部包“获取”父类的关键能力(比如配置、工具逻辑),推荐更清晰、可控的方式:-
提供 public 的受控访问方法:在父类中添加
public final String getSecretKey(),内部返回secretKey;子类可重写该方法增强逻辑。 - 用 package-private + 友元包机制(谨慎):将核心资产设为包私有(默认修饰符),并把子类和必要协作类放在同一包下——适合模块内聚强的场景。
-
引入接口抽象:定义
CoreAssetProvider接口,由父类实现,子类继承后自然获得契约能力,调用方只依赖接口。

















