Constructor 的核心作用是确保对象创建时即处于可用、一致状态;它必须与类名同名、无返回类型、不可被 static/final/abstract 修饰,且是对象生命周期中唯一强制执行的初始化入口。

Constructor 的核心作用就是确保对象一创建就处于可用、一致的状态。它不是“可选的初始化方式”,而是 Java 中对象生命周期里唯一强制执行的初始化入口——只要你用 new,就一定会走它。
Constructor 必须满足的三个硬性条件
不满足任意一条,编译直接报错,不会等到运行时:
- 方法名必须和类名完全一致(大小写敏感),比如类叫
Person,构造方法只能是Person(),不能是person()或PersonBuilder() -
不能写返回类型,连
void都不允许;写了就变成普通方法,new时根本不会调用它 - 不能被
static、final、abstract等修饰——它天生绑定单个实例,静态或抽象都违背语义
常见错误现象:
写成 public void Person(String name) → 编译通过但不是构造方法,new Person("Alice") 看似成功,实则成员变量仍是默认值(null、0、false)
带参构造 vs 无参构造:什么时候必须显式写?
- 如果你没写任何构造方法,编译器自动补一个无参的
Person(),什么也不做,靠成员变量默认值撑着 - 一旦你写了任意一个构造方法(比如
Person(String name)),编译器就不再生成默认无参构造 - 后果:子类若没显式调用
super(...),就会编译失败,因为找不到可匹配的父类无参构造
所以:
- 需要支持无参创建(如框架反射实例化、JSON 反序列化)?必须手动补上
public Person() {} - 只想强制传参(比如
id和name不允许为空)?那就只留带参构造,把无参堵死
在 Constructor 里能做什么、不能做什么
能做的:
- 对参数做基础校验:
if (name == null || name.trim().isEmpty()) throw new IllegalArgumentException("name cannot be blank") - 初始化集合字段:
this.hobbies = new ArrayList();(避免后续NullPointerException) - 调用
this(...)委托同一类其他构造方法(必须是第一行) - 设置不可变字段:
this.createdAt = System.currentTimeMillis();
不能做的:
- 调用可能被子类重写的方法(如
this.init();),子类字段尚未初始化,极易 NPE - 执行 I/O 操作(文件读取、HTTP 请求),阻塞对象创建,且破坏单元测试隔离性
- 直接抛出受检异常(
IOException)却不声明 throws——构造方法本身不支持抛出未处理的受检异常(除非包装成RuntimeException)
关键点其实就一个:构造方法不是“写完就能用”的通用初始化钩子,它是对象诞生那一刻的唯一可信契约。很多人在 init() 方法里堆逻辑,却忘了如果没人主动调它,对象就永远卡在半初始化状态——而 Constructor 至少保证了“只要对象存在,这段代码一定跑过”。










