protected是跨包子类访问的唯一通行证,default成员可继承但不可访问,private不可继承也不可访问,public无条件可见;重写时权限不能变窄。

检查父子类跨包继承时的可见性,关键看 protected 和 default(包私有) 这两个修饰符的行为差异。public 和 private 在跨包场景下表现明确(前者全可见、后者全不可见),真正容易混淆的是 protected ——它专为跨包子类设计,是唯一打破包边界的“继承友好型”权限。
protected 是跨包子类访问的唯一通行证
当子类与父类不在同一个包中时:
- 父类用 protected 修饰的成员(字段、方法):子类可以直接访问(包括通过
super或继承后调用),哪怕跨包也允许 - 父类用 default(不写修饰符)修饰的成员:子类即使继承了,也无法访问——编译报错,因为 default 权限严格限制在本包内,继承关系不豁免包边界
- 父类用 private 修饰的成员:子类既不能访问,也不能继承,完全隔离
- 父类用 public 修饰的成员:子类当然可以访问,但这是“无条件通行”,不体现继承特异性
重写时权限不能变窄,否则编译失败
子类重写父类方法时,访问权限必须 ≥ 父类原权限。跨包继承下这条规则特别容易踩坑:
- 如果父类方法是
protected void show(),子类重写时不能写成void show()(default)或private void show(),否则报错:attempting to assign weaker access privileges - 合法的重写可以是:
public void show()(升权)或保持protected void show()(同权) - 这条限制只针对可继承成员(即非 private),且仅在重写时生效,不是重载
继承性本身不等于可见性
一个成员能否被子类“继承”,和子类能否“访问”它是两件事:
- 能继承但不可访问:default 成员可被跨包子类继承(即子类对象内存中存在该字段/方法),但子类代码中无法直接调用或引用——编译不通过
- 不能继承就谈不上访问:private 成员连继承都不发生,子类里既没有该成员的副本,也不能通过任何方式(包括 get/set)间接暴露其原始形态
- 验证方式很简单:在子类中尝试写
super.xxx或直接使用继承来的xxx,编译器会立刻告诉你是否可见
实际检查步骤建议
遇到跨包继承可见性问题,按顺序确认这四点:
- 父类成员用了什么修饰符?重点关注是不是
protected - 子类是否确实继承了该父类(
extends关系成立)? - 子类与父类是否在不同包中?(看 package 声明)
- 子类中是想“调用”还是“重写”?调用看当前修饰符是否允许;重写还要检查权限是否没变窄
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











