抽象类可定义构造方法,用于初始化继承字段和公共逻辑,须用protected修饰;子类构造器首行必须调用super()或super(参数),以执行父类构造逻辑并确保正确初始化。

抽象类可以有构造方法,但不能被直接实例化;它的构造方法只在子类创建对象时被调用,用于初始化继承来的字段和公共逻辑。
抽象类中如何编写构造方法
写法和普通类完全一样:方法名必须与类名相同,没有返回类型(连 void 也不能写),通常推荐用 protected 修饰:
- 不能用 private——子类无法访问,编译失败
- 不建议用 public——抽象类本就不能 new,public 没实际意义
- 可重载多个构造方法,适配不同初始化场景(如只传 name,或同时传 name 和 timeout)
- 可以在构造方法中给 final 字段赋值、校验参数(如非空、正数)、初始化共享资源(如 Logger)
- 避免在构造方法中调用抽象方法——此时子类字段可能还没初始化,容易出 NullPointerException
子类如何调用抽象父类的构造方法
Java 编译器强制要求:每个子类构造器的第一条语句,必须是 super() 或 super(参数)。这条规则对抽象类完全适用:
- 如果抽象父类有无参构造,子类可不写 super(),编译器会自动插入
- 如果抽象父类只有带参构造(比如
protected Animal(String name)),子类就必须在第一行写super(name),否则编译报错 -
super()必须是子类构造器的第一条语句,不能和this()共存 - 调用的是父类自己的
<init></init>方法,JVM 通过invokespecial指令执行,不进行动态绑定
构造方法的实际作用不是创建父类对象
执行 new Dog() 时,JVM 先分配内存并设默认值,再按顺序执行:
- 父类实例初始化块(
{})→ 可能调用子类实现的抽象方法(危险但合法) - 父类构造方法体 → 执行你写的校验、赋值等逻辑
- 子类实例初始化块
- 子类构造方法体
整个过程操作的是同一个对象——它是 Dog 类型的实例,只是在初始化阶段复用了抽象父类的构造逻辑。
一个简单示例
假设抽象类定义如下:
abstract class Animal {
protected final String name;
Animal(String name) {
if (name == null || name.trim().isEmpty())
throw new IllegalArgumentException("name cannot be blank");
this.name = name;
}
}
子类必须显式调用:
class Dog extends Animal {
Dog(String name) {
super(name); // 必须写,且必须是第一行
System.out.println("Dog created: " + name);
}
}
这样既完成了父类字段初始化,又把参数校验逻辑统一收口,子类无需重复处理。










