抽象类必须用abstract修饰,含abstract方法的类必须声明为abstract;abstract类可无abstract方法但失去约束意义;abstract方法不能有方法体、private或static;适合模板方法模式封装固定流程与可变环节。

抽象类必须用 abstract 修饰,但不是所有带 abstract 的类都合法
Java 要求:只要类里有一个 abstract 方法,这个类就必须声明为 abstract;反过来,abstract 类可以没有 abstract 方法,但这样设计通常没意义——它就退化成普通类的“假抽象”,失去约束子类行为的作用。
常见错误是漏写 abstract 类修饰符,编译直接报错:error: abstract method in non-abstract class。还有一种隐蔽坑:在 abstract 类里写了 abstract 方法,却忘了加 abstract 关键字(比如写成 void foo(); 而非 abstract void foo();),JVM 会把它当普通方法处理,导致子类不重写也能编译通过,破坏设计意图。
-
abstract类不能被new实例化,哪怕它所有方法都有实现 - 子类继承
abstract类,要么自己也声明为abstract,要么实现全部未实现的abstract方法 - 构造器可以存在,且会被子类
super()调用——它负责初始化父类中已定义的字段和逻辑
abstract 方法不能有方法体,也不能是 private 或 static
abstract 方法本质是契约,只声明“做什么”,不规定“怎么做”。所以语法上禁止大括号 {},也不允许 private(子类根本看不见)、static(静态方法属于类本身,无法被子类重写)。
典型误用:把工具方法误设为 abstract,比如 abstract static String format(Date d);,编译器会立刻拒绝:illegal combination of modifiers: abstract and static。如果真需要共用逻辑,应该抽成 protected 或 final 的具体方法,在抽象类内部调用。
立即学习“Java免费学习笔记(深入)”;
-
abstract方法默认是public或protected,不能显式写private abstract void foo(); - 接口里的默认方法(
default)和静态方法(static)可共存,但抽象类不支持default修饰符 - 抽象方法的参数、返回类型、异常声明,都会成为子类重写时的强制约束
抽象类适合封装“固定流程 + 可变环节”,比如模板方法模式
这是抽象类最不可替代的场景:把算法骨架写死在 final 方法里,把变化点拆成 abstract 方法交给子类定制。比如一个导出报表的流程:validate() → fetch() → transform() → save(),其中 validate() 和 save() 是通用逻辑,而 fetch() 和 transform() 必须由子类决定数据源和格式。
这时候如果用接口,只能声明方法,没法提供 validate() 这样的复用代码;如果全用具体类,又无法强制子类实现关键步骤。抽象类正好卡在这个中间位置。
- 模板方法本身应声明为
final,防止子类覆盖整个流程 - 被子类实现的钩子方法(hook method)用
abstract声明,确保不被跳过 - 如果某个环节可选,就用
protected空实现,而非abstract,避免子类被迫实现无用逻辑
和接口混用时,抽象类优先提供状态和复用逻辑,接口负责能力契约
Java 8+ 允许接口有 default 方法,容易让人混淆该用哪个。简单判断:如果需要字段(private String token;)、构造器、或复杂初始化逻辑,必须用抽象类;如果只是声明“能做什么”(比如 Comparable、Runnable),用接口更轻量、更利于多实现。
实际项目里常组合使用:一个抽象类实现核心状态与基础行为,再 implements 若干接口表达额外能力。比如 abstract class DatabaseConnector implements Closeable, AutoCloseable —— 状态和连接逻辑在抽象类里,关闭资源的契约由接口承担。
- 抽象类只能单继承,接口可以多实现,设计时先想清楚“是不是真需要共享状态”
- 抽象类中的
protected字段或方法,对子类是可见的;接口里所有东西默认public,没有访问控制余地 - 如果未来可能让非继承关系的类具备相同能力,优先从接口开始设计
abstract,结果子类被迫实现一堆空壳;或者相反,把本该强制定制的环节写成具体方法,导致后续扩展只能靠复制粘贴。边界感得靠几次重构才能找准。










