Java中protected成员访问由编译期规则严格定义:同包内任意类可直接访问(等价package-private);跨包子类仅能通过this或自身实例访问继承的成员,不可通过父类引用调用。

Java 中 protected 成员在跨包子类中的访问,不是靠“配置”实现的,而是由语言规范严格定义的编译期规则。它不依赖注解、IDE 设置或 JVM 参数,只取决于包结构、继承关系和调用上下文。核心是理解“谁在哪儿、以什么方式访问”。
同一包内:无需继承也能直接访问
只要子类和父类在同一个包中,protected 成员对包内任意类都可见——不管是否继承、是否是静态方法、是否通过 this 或其他实例调用。
- 例如:
Parent p = new Parent(); p.protectedMethod();在同包的Helper类中完全合法 - 这种行为等价于 package-private(默认权限),只是多了“跨包子类可用”这一条
跨包子类:只能访问“自己继承来的”,不能碰“父类实例”
当子类在不同包时,protected 成员仅在其自身实例方法中,通过 this 或子类实例(如 new Child())访问才被允许;任何用 Parent 类型引用指向子类对象或父类对象的调用都会失败。
- ✅ 合法:
this.protectedField、protectedMethod()、new Child().protectedMethod() - ❌ 编译错误:
new Parent().protectedField、Parent p = new Child(); p.protectedMethod()、static void main() { new Child().protectedMethod(); }(静态方法本身不是实例上下文)
安全暴露字段:别直接给 protected 字段,改用受控方法
如果目标是让跨包子类“读取但不破坏封装”,应把字段设为 private,提供 protected 或 public 的 getter 方法。这样既能控制访问逻辑(比如加日志、校验、延迟加载),又避免子类强依赖字段名或类型。
立即学习“Java免费学习笔记(深入)”;
- 推荐写法:
private final String token; protected String getToken() { return token; } - 若需子类可修改状态,不要暴露字段,而是提供
protected void initToken()这类钩子方法,把赋值逻辑收归父类控制
构造器的特殊限制:protected 构造器不能跨包 new
声明为 protected 的构造器,只允许同包类直接调用,或跨包子类在 super() 中隐式/显式调用。它不能被跨包子类以外的代码通过 new Parent() 调用。
- 子类构造器中:
super(arg);✅ 允许 - 子类普通方法中:
new Parent();❌ 编译失败 - 同包其他类中:
new Parent();✅ 允许(因为同包)


















