抽象方法必须定义在abstract类中,不能独立存在;它无方法体,可有访问修饰符(非private/final)、参数、返回类型和异常声明;子类继承时须实现所有抽象方法,否则必须声明为abstract。

抽象方法必须定义在 abstract 类里
Java 中的 abstract 方法不是独立存在的语法元素,它只能出现在用 abstract 修饰的类中——哪怕这个类里只有一个抽象方法,整个类也必须声明为 abstract class。否则编译器会报错:error: abstract method in non-abstract class。
常见误操作是直接在普通 class 里写 public abstract void doSomething();,这会立刻编译失败。
- 抽象方法不能有方法体(即不能有
{}),连空花括号都不行 - 抽象方法可以有访问修饰符(
public、protected),但不能是private或final - 抽象方法可以有参数、返回类型、异常声明,和普通方法一样完整
子类继承 abstract 类时,必须实现所有抽象方法
这是“强制子类实现”的核心机制。只要子类不是也声明为 abstract,它就必须用 public(或至少不低于父类可见性)重写每一个未实现的抽象方法。
例如父类有 abstract String getName();,子类若写成 protected String getName() { return "x"; },编译会拒绝:因为可见性降低了;若完全不写这个方法,且子类没加 abstract,则报错:class X must either be declared abstract or implement abstract method getName() in Y。
立即学习“Java免费学习笔记(深入)”;
- 子类可以用
@Override显式标注(推荐),但不是强制 - 如果子类自己也定义了新抽象方法,那它必须是
abstract类 - 接口中的
default方法不会覆盖抽象类里的抽象方法,二者不冲突
抽象方法 vs 接口方法:设计意图不同
抽象方法强调“**是什么行为,由谁来决定怎么做**”——父类划出契约边界,具体逻辑交由子类填充。它天然绑定继承关系,适合表达“is-a”语义(比如 Animal 定义 abstract void move();,Dog 和 Bird 各自实现)。
而接口方法(尤其是 Java 8+ 的 default 和 static)更偏向“能力组合”,支持多实现。别为了省几行代码把本该用抽象类建模的层级关系,硬塞进接口里。
- 抽象类可以有构造器、成员变量、普通方法;接口不能有构造器,字段默认
public static final - 一个类只能继承一个抽象类,但可实现多个接口
- 抽象方法无法被
static或final修饰,这点和接口中的static方法本质不同
运行时没有抽象方法的“实例”,只有具体实现
你永远不能用 new Animal() 创建抽象类实例,JVM 在加载类时就会检查:如果某个类含有未实现的抽象方法,且不是 abstract 类,就抛 java.lang.VerifyError。所以抽象方法的存在,本质上是编译期 + 类加载期的双重约束工具。
真正起作用的是子类对象调用时绑定的具体实现——JVM 通过虚方法表(vtable)完成动态分派,抽象方法本身不占运行时空间,也不参与实际执行。
- 反射可以获取抽象方法(
Method.isSynthetic()返回 false,Modifier.isAbstract()返回 true),但不能调用 - 序列化/反序列化不涉及抽象方法,只处理字段和具体逻辑
- 测试抽象类时,通常用匿名子类或 Mockito 的
mock(AbstractClass.class)来绕过实例化限制











