构造器用于创建对象时自动执行初始化逻辑,包括赋初值、参数校验与状态建立;其无返回类型、名称须与类名一致,由jvm在new时强制调用;支持无参、有参及重载,可通过this()复用;需注意初始化顺序、避免子类重写方法调用、防御性复制可变对象,并配合final字段实现不可变性;record语法进一步简化不可变数据的初始化。
构造器的作用就是在创建对象时自动执行初始化逻辑,包括给属性赋初值、校验参数、建立内部状态等。只要在类中定义了构造器(尤其是带参构造器),new 对象时就会立即调用它,完成属性初始化。
明确构造器的声明与调用时机
构造器不是普通方法,它没有返回类型(连 void 都不能写),名字必须和类名完全一致。JVM 在执行 new 表达式时,会先分配内存,再立即调用匹配的构造器——这个过程不可跳过,也不可延迟。
- 无参构造器:适合默认初始化,比如把字符串设为 "",数字设为 0,集合设为 new ArrayList()
- 有参构造器:适合强制要求外部提供关键数据,例如 Person(String name, int age) 中直接将 name 和 age 赋给对应字段
- 可以重载多个构造器,通过 this() 调用其他构造器实现复用,避免重复赋值代码
在构造器里安全地初始化属性
属性初始化不等于简单赋值。要注意顺序、可见性与副作用:
- 字段声明顺序不影响初始化顺序,但构造器内语句顺序决定执行顺序;建议先校验参数(如 throw new IllegalArgumentException("age must be > 0")),再赋值
- 避免在构造器中调用可能被子类重写的方法(即非 final 方法),否则可能导致子类字段未初始化就被访问
- 如果属性是可变对象(如 List、Map),建议在构造器中新建实例并赋值,而不是接收外部引用,防止后续被意外修改
配合 final 字段做不可变初始化
final 字段只能在声明时、构造器中或初始化块里赋值一次。构造器是唯一能根据传入参数动态设置 final 字段的地方:
- public final String id; public final List
tags; - 在构造器中写 this.id = generateId(); this.tags = new ArrayList(inputTags); 就能确保对象构建完成后所有 final 字段已确定且不可变
- 这样既保证线程安全,又让对象语义更清晰——一旦 new 出来,状态就固定了
现代写法:用记录类(record)简化初始化
Java 14+ 的 record 是专为不可变数据建模设计的语法糖。它自动生成私有 final 字段、公共读取方法、构造器、equals/hashCode/toString:
- record Point(int x, int y) { } 编译后自带 public Point(int x, int y) 构造器,自动完成 x 和 y 的初始化
- 你仍可定义自定义构造器(含参数校验),只需调用 this(...) 委托给隐式生成的全参构造器即可
- 适合 DTO、配置项、领域事件等“纯数据”场景,省去模板代码,初始化逻辑一目了然











