抽象类访问修饰符设计核心是用protected和final控制子类覆写范围:protected封装可扩展点(如钩子方法),final锁定不可变流程(如模板方法);慎用private/package-private;构造器必须protected。

抽象类中访问修饰符的设计,核心是用 protected 和 final 搭配控制子类的可覆写范围,而非靠 private 或 public 划界。
用 protected 封装可扩展点
把希望子类参与实现或定制的部分声明为 protected,既避免外部调用干扰,又保留继承链内的可见性。比如模板方法中留出的钩子方法:
- 抽象方法默认就是
protected abstract(即使不写修饰符,Java 也按protected处理) - 具体但允许重写的钩子方法,显式写
protected void beforeProcess() {} - 避免用
public声明钩子方法——这会让外部直接调用,破坏模板逻辑顺序
用 final 锁定不可变行为
对已定义完整、不允许子类改动的核心流程,用 final 修饰方法,强制子类只能在允许的位置介入:
- 模板方法本身必须是
final,例如public final void execute() { prepare(); doWork(); cleanup(); } - 关键校验或资源管理逻辑,若语义固定,也应设为
final - 注意:
final方法不能是private,否则子类无法调用,会破坏模板结构
慎用 private 和 package-private
private 成员仅对当前类可见,子类完全无法访问,不适合作为“可扩展契约”的一部分;而 package-private(默认)虽允许同包子类访问,但依赖包边界,缺乏设计意图表达:
立即学习“Java免费学习笔记(深入)”;
- 字段尽量设为
private,通过protected的 getter/setter 控制访问粒度 - 避免默认访问权限的方法作为扩展点——它把约束隐含在包结构里,易被误用或跨包继承时失效
- 如果某个辅助逻辑只供本类使用,且与子类无关,才用
private
构造器与初始化逻辑的可见性
抽象类构造器必须是 protected,否则子类无法实例化;初始化逻辑要区分“一次性准备”和“每次执行前准备”:
- 构造器一律用
protected,禁止public(抽象类不能直接 new) - 需要子类传参初始化的字段,在构造器中接收并赋值,后续由
protected方法封装使用 - 避免在构造器中调用
protected或abstract方法——子类对象尚未构建完成,可能导致空指针或状态错乱


















