构造函数应仅执行轻量同步初始化,复杂逻辑(如异步加载、依赖注入)须移至显式调用的 init() 方法中,并通过 _initialized 标志保证幂等性;用户需先调用 init() 再使用实例。

构造函数本身不适合执行复杂初始化,尤其涉及异步、依赖加载或条件分支时。正确做法是把“初始化”从构造过程剥离,转为显式调用的独立方法(如 init()),让构造函数只做轻量、同步、确定性的设置。
构造函数只负责基础状态准备
它应完成以下几件事:分配必要字段、绑定关键方法、设置默认配置、缓存参数——全部必须是同步操作。
- 避免在构造函数里发起网络请求、读取 localStorage、等待定时器
- 不要调用可能返回 Promise 的函数,也不要 await 或 return Promise
- 可接受传入已就绪的依赖(如一个已创建好的 API client 实例)
把复杂逻辑移到 init() 方法中
定义一个返回 Promise 的 init() 方法,在其中集中处理异步加载、权限校验、数据预热等流程。该方法可被多次调用,但通常配合状态标记(如 this._initialized)实现幂等性。
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
- 首次调用时执行真实初始化,并缓存结果(成功值或错误原因)
- 后续调用直接返回已缓存的 Promise,不重复执行
- 其他业务方法在执行前检查 this._initialized === true,未完成则 await this.init()
暴露清晰的使用契约
用户创建实例后,需明确知道“不能直接用,得先 init”。可在文档、类型定义或运行时提示中强化这一约定:
立即学习“Java免费学习笔记(深入)”;
- 类名后加 Async 后缀(如 DataLoaderAsync)暗示需异步初始化
- constructor 中抛出提示性错误(如 "Call .init() before using"),当访问关键属性或方法时触发
- 提供静态工厂方法(如 DataLoaderAsync.create()),内部自动调用 init 并返回已就绪实例
需要继承时注意 super() 和初始化顺序
子类 constructor 必须第一行调用 super(),但此时父类尚未完成复杂初始化。因此:
- 父类的 init() 应设计为可安全多次调用,子类可在 super() 后立即 await this.init()
- 避免在父类 constructor 中访问子类重写的属性或方法(它们还未定义)
- 若子类有额外初始化步骤,应在自己的 init() 中组合调用 await super.init()

















