子类重写父类方法时访问权限只能扩大或保持不变,绝不能缩小——这是Java编译器强制的硬性规则;public方法必须重写为public,protected可升为public或保持protected,包私有可升为protected/public(同包内),private/static/final方法不参与重写。

子类重写父类方法时,访问权限只能扩大或保持不变,绝不能缩小——这是 Java 编译器强制执行的规则,不是风格建议,而是编译期硬性约束。
哪些权限调整是合法的
调整必须符合可见性层级(public > protected > 默认(包私有) > private),且仅适用于真正可被继承的方法:
- 父类是 public → 子类重写必须是 public(无法再扩大,也不允许降级)
- 父类是 protected → 子类可用 protected 或 public
- 父类是 默认(无修饰符) → 子类可设为 默认、protected 或 public(但仅限同包内重写)
哪些情况根本不算“重写”
以下情形不触发重写规则,因为不具备继承基础:
- private 方法:对子类不可见,子类中同名方法只是独立声明,与父类无关
- static 方法:属于类而非对象,子类中同名方法是“隐藏”(hiding),不是重写
- final 方法:明确禁止覆盖,子类若声明同签名方法会直接编译失败
为什么不能缩小权限
核心是为了保障多态调用安全和里氏替换原则:
立即学习“Java免费学习笔记(深入)”;
- 假设 Animal a = new Dog();,调用 a.run() 时,编译器只检查 Animal 中 run() 的声明权限
- 若子类擅自把 public run() 改成 protected,运行时仍会尝试调用子类版本,但因权限不足而失败
- 编译器提前拦截(报错 Cannot reduce the visibility),把问题挡在运行前
实际开发中的关键提醒
别依赖直觉,要用工具和规范守住底线:
- 务必添加 @Override 注解——它不是装饰,而是编译期契约,能捕获拼写错误、签名不匹配、误删父类方法等静默风险
- 不要试图绕过规则:哪怕父类方法是 protected,你把它改成 public 是允许的;但改成 private 或默认(跨包时)会立刻编译失败
- 权限扩大不会让父类引用“突然看到”新方法,但它确保了多态链路畅通:父类引用调用时,仍走重写逻辑,且不会因权限问题中断


















