抽象类不能new,但必须有构造方法:因其需为子类初始化继承的字段,子类构造时默认或显式调用super()触发该链;父类仅有有参构造时,子类必须显式调用super(参数),否则编译失败。

抽象类不能 new,但能写构造方法——这不是语言的漏洞,而是设计上的精准分工:构造方法负责“初始化”,实例化要求“行为完整”。两者本就不绑定。
构造方法是为子类准备的初始化入口
抽象类的构造方法不会被直接调用,只在子类创建对象时,作为初始化链的一环被执行。JVM 在执行子类构造器时,会自动插入或要求显式调用 super(),从而触发抽象父类的构造逻辑。
- 哪怕子类构造器里没写 super(),编译器也会默认插入对父类无参构造的调用
- 如果抽象类只提供带参构造(比如 Animal(String name)),子类就必须显式写 super(name),否则编译失败
- 构造体内可做参数校验、字段赋值、日志记录、资源预加载等,和普通类完全一致
无法实例化是编译期的语义禁令
Java 在编译阶段就拒绝生成抽象类的对象结构,不是运行时抛异常,而是语法层面直接报错。只要类声明了 abstract,或含有未实现的抽象方法,它就被视为“不完整类型”。
- 编译器不为其生成对象头、字段偏移、虚函数表等运行时信息,因为它缺少可确定的行为契约
- 即使抽象类一个抽象方法都没有,仅靠 abstract 关键字修饰,new AbstractClass() 仍会编译失败
- 这种限制与接口不同:接口连状态都不承载;抽象类承载状态和部分行为,只是主动留白关键行为
抽象性 ≠ 残缺,而是“待补全”的契约
抽象类像一份带组装说明的图纸:构造方法是说明书里的初始化步骤,但它本身不是成品。子类继承它,填上抽象方法的具体实现,才构成一个行为明确、可独立存在的具体类型。
- 它封装共用字段(如 id、createTime)、共用非抽象方法、以及必须由子类回答的问题(抽象方法)
- 所有子类对象都强制走同一套初始化流程,避免重复代码,也确保基础状态合法
- Spring 等框架创建子类 Bean 时,依然完整执行这条构造链,抽象父类的构造逻辑照常生效
常见误解需要划清界限
这几个概念不能混为一谈:
- 有构造方法 ≠ 能 new:构造方法解决“怎么初始化”,new 解决“能不能当完整对象用”
- 抽象类不是没意义的空壳:它承担模板职责,把通用初始化、约束检查、依赖准备都收束到一处
- 接口没有构造方法,原因完全不同:接口不维护状态,也不参与对象初始化,只定义能力契约
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











