




抽象方法必须定义在abstract类中,无方法体、以分号结尾,不能用private/static/final/native修饰,子类必须实现(除非自身也为abstract),且需保持签名一致、遵循异常与返回类型规则。
抽象方法必须定义在 abstract 类中,且不能有方法体(即无花括号和实现代码),末尾以分号结束。
abstract 修饰符 + 返回类型 + 方法名 + 参数列表 + 分号常见错误是给抽象方法写了大括号或返回值语句,这会导致编译失败:
abstract class Animal {
// ✅ 正确:无方法体,以分号结尾
abstract void makeSound();
// ❌ 错误:写了方法体,编译报错 "abstract methods cannot have a body"
abstract void sleep() {
System.out.println("sleeping...");
}
// ❌ 错误:写了 return,也是非法方法体
abstract String getName() {
return "unknown";
}
}
private、static、final 或 native 修饰 —— 它们与“强制子类重写”的语义冲突public 或 protected(默认包访问权限也允许),但不写访问修饰符时,子类必须在同一包内才能继承并实现
abstract T process(String input) throws IOException;
抽象类不是“全抽象”的容器,它常用来提供部分通用逻辑,把可变行为留给子类实现。比如模板方法模式就依赖这种混合结构:
abstract class DataProcessor {
// ✅ 非抽象方法:封装流程骨架
public final void execute() {
validate();
parse();
transform();
save();
}
// ✅ 抽象方法:由子类决定具体怎么处理
abstract void parse();
abstract void transform();
abstract void save();
// ✅ 普通方法:所有子类共享的基础校验
void validate() {
System.out.println("Validating input...");
}
}
execute() 是 final 的,防止子类破坏流程顺序validate() 是普通方法,子类可直接复用,也可通过 super.validate() 扩展abstract;反过来,abstract 类可以没有抽象方法(但很少见,通常用于禁止实例化)abstract
这是编译器强制执行的契约。未实现的抽象方法会让子类变成“不完整类型”,无法被实例化:
class Dog extends Animal {
// ❌ 编译错误:Dog 不是 abstract 的,却未实现 makeSound()
}
abstract class Cat extends Animal {
// ✅ 允许:Cat 自己也是 abstract,可以延迟实现
}
class Bird extends Animal {
// ✅ 正确:实现了所有抽象方法
@Override
void makeSound() {
System.out.println("Chirp!");
}
}
Animal,子类可返回 Dog)throws IOException,子类实现可以不抛出异常,或抛出其子类,但不能抛出更宽泛的异常(如 Exception)default)不能覆盖抽象类中的抽象方法;若同时继承抽象类并实现接口,必须显式实现该方法抽象方法本质是 API 契约的声明,不是功能实现。最容易被忽略的是访问修饰符对子类可见性的影响——比如父类抽象方法用默认(包级)访问,而子类在另一个包里,即使写了 @Override,编译器也不会识别为合法实现,而是当作一个全新方法。