protected是继承链内可见的访问控制机制,允许子类在自身实例上下文中访问继承的成员,但禁止非继承关系的跨包访问。

protected 在跨包继承中不是“让子类随便用父类东西”的开关,而是有明确访问主体和上下文限制的继承可见性机制。它允许子类复用父类实现细节,但禁止无关代码越权操作。
子类能合法访问 protected 成员的三种情况
只要子类正确继承了父类(即使跨包),以下写法在子类的实例方法、构造器或初始化块中全部编译通过:
- 直接写 fieldName 或 this.fieldName
- 显式用 super.fieldName 调用父类版本
- 创建本类新实例访问:new Child().fieldName
常见编译失败的典型场景
这些写法看似合理,实际在子类所在包中会直接报错:
- Parent p = new Child(); p.fieldName; → 编译错误:“has protected access in Parent”
- new Parent().fieldName; → 不属于子类继承链上的对象,不可见
- 同包子类中,非子类工具类(如 Helper)尝试访问 new Parent().fieldName → 无继承关系,不被允许
protected 的本质是“继承链内可见”,不是“跨包开放”
编译器检查的是:调用是否发生在子类自身实例上下文中,且访问的是自己继承来的那一份状态。运行时对象的实际类型不影响编译判定——new Child() 可以,new Parent() 就不行,哪怕 Child 是 Parent 的子类。
更安全的实践建议
裸露 protected 字段容易导致状态被随意修改,推荐:
- 字段设为 private,提供 protected final String getXXX() 方法
- 需要子类可变逻辑时,封装为 protected void initXXX() 模板方法
- 核心状态优先用 protected final,避免运行时污染
- 跨包子类协作,比字段暴露更稳的方式是定义接口 + 父类实现契约
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











