抽象类会有构造函数吗
→ 返回 面试
有。 抽象类可以定义构造器,只是不能 new 抽象类本身;子类实例化时会通过 super(...) 间接调用抽象类构造器,用于初始化父类共享字段。
与接口对比见 接口与抽象类。
结论速记
| 类型 | 能否有构造器 | 能否直接 new | 构造器谁调用 |
|---|---|---|---|
| 普通类 | 能 | 能 | 自己或外部 |
| 抽象类 | 能 | 不能 | 子类 super(...) |
| 接口 | 不能(无实例) | 不能 | — |
为什么抽象类需要构造器
抽象类常承载子类共享的状态(字段),这些字段需要在对象创建时初始化:
public abstract class Animal {
protected String name;
// 抽象类构造器:子类必须通过 super 调用
public Animal(String name) {
this.name = name;
}
public abstract void speak();
}
public class Dog extends Animal {
public Dog(String name) {
super(name); // 调用抽象类构造器
}
@Override
public void speak() {
System.out.println(name + ": 汪汪");
}
}
// new Animal("x"); // 编译错误:抽象类不能实例化
Animal d = new Dog("旺财"); // OK:实际创建的是 Dog,构造链完整执行顺序:new Dog("旺财") → Dog 构造器 → super(name) → Animal 构造器 → 初始化 name → 回到 Dog 构造器体 → 对象就绪。
常见追问
不写构造器会怎样?
与普能类一样:编译器自动生成无参默认构造器。若抽象类只写了有参构造器、未写无参构造器,子类必须显式 super(参数),否则编译报错。
public abstract class Base {
public Base(int id) { /* ... */ }
}
public class Sub extends Base {
public Sub() {
super(1); // 必须,因为 Base 没有无参构造器
}
}抽象类构造器可以是 private 吗?
可以(语法合法),但会限制只有同文件内的静态内部子类等能访问;公开继承体系里几乎不用。工具类更常用 final class + private 构造器,而非抽象类。
抽象类构造器里能调抽象方法吗?
技术上可以编译,但不推荐:构造器执行时子类尚未初始化完成,若抽象方法已在子类实现,可能读到子类字段的默认值(尚未赋值),行为难料。实践上构造器只做字段赋值,不调多态方法。
和接口的区别(面试对比)
| 对比 | 抽象类 | 接口 |
|---|---|---|
| 构造器 | 有 | 无 |
| 实例字段 | 可有 | 只有 public static final 常量 |
| 目的 | 共享状态 + 部分实现 | 定义能力契约 |