不能降低访问权限;java规定子类重写父类方法时,访问权限只能扩大或保持不变:父类public方法子类必须public,protected可升为public或保持protected,default可升为protected或public,否则编译失败。

初学者在继承中重写方法时容易忽视访问权限红线,核心在于“能编译、能跑通、一上线就出错”的隐蔽性——权限问题不报语法错误,也不影响同包测试,却直接破坏多态调用和容器集成能力。
默认可见性陷阱:没写public,就等于锁死在包内
Java 中未显式声明访问修饰符的方法,默认是包级(default)可见。初学者常以为“只要方法名对、参数对,就能重写”,却忽略:父类方法是 public(如 Servlet 的 doFilter),子类若只写 void doFilter(...) 而漏掉 public,实际生成的是包私有方法。外部容器(如 Tomcat)通过反射调用时,因不可见而静默跳过或抛 IllegalAccessError。
- 抽象基类(如
AbstractFilter)通常只定义模板逻辑,不强制子类补全public - IDE 自动生成的
@Override方法常默认带public,但手动删掉后毫无警告 - 单元测试常与被测类同包运行,包内调用一切正常,掩盖问题
契约意识缺失:不知道接口/规范已暗定 public
Servlet 规范要求 Filter 接口所有方法必须是 public;Spring 的 OncePerRequestFilter 等抽象类虽未重复声明,但继承自该契约。初学者误以为“继承抽象类就够了”,却忘了:实现规范接口,就必须满足其全部约束,包括可见性。
- 接口方法隐式为
public,实现类中@Override方法必须显式public - 框架容器(如 Spring Boot 启动器)依赖反射调用,只认
public方法 - 跨模块调用(如权限中间件反射读取
getAllowedPaths())失败,往往归因为“方法不存在”,实则是不可见
权限收缩误判:以为“protected 更安全”,实则违反里氏替换
有些初学者为“限制访问”主动把父类 public 方法重写成 protected,这会直接触发编译错误:Cannot reduce the visibility。但更隐蔽的是:他们可能根本没意识到这是编译期强制规则,还以为是风格选择。
- 父类
public→ 子类只能public(不能protected、default或private) - 父类
protected→ 子类可protected或public,但降为default同样编译失败 - 该限制不是建议,而是 JVM 多态安全的底层保障:父类引用指向子类对象时,必须保证所有公开契约仍可用
构造与工具方法同样踩坑:不止是重写方法
权限红线不限于 @Override 方法。初学者常在新增辅助方法或构造器上栽跟头:
- 自定义
validateToken()工具方法没加public,后续被其他组件反射调用失败 - 用 Lombok
@RequiredArgsConstructor生成构造器,默认是package-private,导致 Filter 无法被容器实例化 - 抽象类中
protected模板方法被子类重写时,误删public导致子类暴露能力不足











