构造方法用于初始化已创建对象而非创建对象;它在new分配内存后执行,负责赋初值、建状态、做检查;无定义时编译器提供默认无参构造,但自定义任一构造则默认消失。

构造方法是用来初始化新创建对象的
Java中构造方法不是用来“创建对象”的——new 操作符负责内存分配和对象创建;构造方法只在对象内存已分配后立即执行,作用是给字段赋初值、建立内部状态、触发必要检查或资源预热。如果没写任何构造方法,编译器会自动插入一个无参、空体的默认构造方法;但只要定义了任意构造方法(哪怕带参数),这个默认构造方法就不再存在。
- 常见错误:子类继承父类时,父类只有带参构造方法,而子类构造方法里没显式调用
super(...),编译直接报错Constructor not defined - 使用场景:需要强制传入不可变字段(如
final String id)、校验参数合法性(如拒绝负数长度)、注册监听器、打开文件句柄等 - 注意:构造方法中调用
this(...)或super(...)必须是第一行语句,且二者不能共存
构造方法重载必须靠参数列表区分
Java不支持返回类型或访问修饰符参与重载判断。两个构造方法即使 public 和 private 不同,只要参数类型、数量、顺序完全一致,就是重复定义,编译失败。
- 典型误用:想用
private MyClass()和public MyClass()实现“内部可无参、外部必须有参”,这行不通——编译器视为重复 - 正确做法:用不同参数组合,例如
MyClass(String name)和MyClass(String name, int age),或引入标记参数如MyClass(String name, boolean internal) - 性能影响:重载本身无运行时开销,但参数类型自动装箱(如传
int调用MyClass(Integer))可能触发不必要的对象创建
构造方法里调用可重写方法会导致未初始化状态泄露
这是最隐蔽也最危险的问题。当构造方法中调用一个被子类重写的方法(包括 protected 或 public 的实例方法),此时子类字段尚未初始化,但子类方法却已执行——拿到的是默认值(null、0、false)。
- 错误现象:子类重写了
init(),父类构造方法末尾调用它,结果子类字段全为null,抛出NullPointerException - 解决方式:把这类逻辑移到工厂方法或构建器中;或把方法声明为
final/private,阻止重写 - 兼容性提醒:该行为在所有JVM版本中一致,不是bug,而是Java对象初始化顺序的固有规则
静态工厂方法正在替代多数公共构造方法
现代Java代码(尤其JDK 8+及主流库)越来越倾向用静态工厂方法(如 LocalDateTime.of(...)、Optional.ofNullable(...))代替 public 构造方法,原因很实际:
立即学习“Java免费学习笔记(深入)”;
- 命名更清晰:
BigInteger.valueOf(long)比new BigInteger(String)更易懂,且避免了字符串解析开销 - 可返回子类或缓存实例:比如
Boolean.valueOf(true)总是返回常量Boolean.TRUE - 支持泛型推导:构造方法无法做
new ArrayList()(Java 7+才支持钻石语法,但仍有局限),而静态方法可以设计成Lists.newArrayList() - 但要注意:静态工厂方法无法被继承,也不能被
super()调用,这点和构造方法本质不同









