核心是让每个成员变量在对象诞生瞬间持有符合业务语义的确定值;优先类内默认初始化,数值设业务初值、引用防null、布尔重意图;构造函数初始化列表用于参数依赖场景,严格按声明顺序且禁跨成员依赖;拒绝语言默认值幻觉,复杂依赖延迟初始化。

核心是让每个成员变量在对象诞生的瞬间,就持有符合业务语义的确定值,而不是依赖语言默认值或侥幸心理。
类内默认初始化器优先使用
在成员声明处直接赋予合理初值,这是最直观、最不易遗漏的方式。它对所有构造路径生效,且编译器能静态验证。
- 数值型字段按业务设默认:比如timeoutMs = 5000、retryCount = 3
- 引用类型不为 null:用空集合、空字符串或工厂方法兜底,如items = new ArrayList()、name = ""
- 布尔型体现业务意图:用isActive = false比isActive = true更安全,避免误开启功能
构造函数初始化列表精准控制
当初始值依赖构造参数或需差异化逻辑时,必须用初始化列表——它在构造函数体执行前完成,且是 const 和引用成员的唯一合法入口。
- 顺序严格匹配声明顺序:即使列表中写成 b(val), a(b * 2),只要 a 先声明,就先初始化 a,此时 b 还未构造,a 会读到垃圾值
- 禁止跨成员依赖:初始化列表中不能用尚未初始化的其他成员计算值,如 a(b + 1) 是危险的
- 资源类优先绑定:文件句柄、锁、智能指针等,应在初始化列表中直接构造并接管,避免构造函数体内异常导致资源泄漏
区分存储期,拒绝“默认即安全”错觉
Java 的成员默认值(0、false、null)和 C++ 静态变量零初始化,只解决内存安全底线,不解决业务合理性。
- null 不等于“无数据”,而是“未准备好”:一个 List
初始为 null,后续任何 add 或 size 调用都直接崩溃 - 0 不代表“有效状态”:购物车总价默认 0.0,会导致 canCheckout() 永远返回 false,测试难覆盖
- char 默认 '\u0000' 易被误判为空格或占位符,在日志、序列化、校验环节引发隐性错误
复杂依赖用延迟初始化或工厂封装
若成员初始化需外部服务、配置加载或耗时计算,不要塞进构造流程,改用可控时机。
- Java 中用 static Holder 模式或 Supplier 包装:确保首次访问才创建,且线程安全
- C++ 中用 std::optional 或 std::unique_ptr 延迟构造,配合 get_or_create() 接口
- 跨文件全局依赖:避免在全局变量初始化表达式中引用另一模块的非常量变量,改用函数内 static 局部变量保证单例与顺序










