




构造方法不参与多态,因其不被继承、不可重写,且对象创建时类型已静态确定;父类构造中调用可重写方法会导致子类字段未初始化而引发空指针或逻辑错误。
不能。Java 中的 构造方法 不是普通方法,它没有返回类型(连 void 都不能写),也不被继承,更不会被重写(@Override 无法标注构造方法)。因此,它天然不满足多态发生的三个前提:继承、重写、向上转型后的动态绑定。
当你写 new A(),JVM 就只会调用 A 类定义的构造方法,哪怕 A 是某个子类的父类,也不会自动“切换”到子类构造——因为对象类型在 new 时就已静态确定。多态只发生在运行时对**已存在对象**的方法调用上,而构造方法执行时对象才刚开始创建。
常见误解场景:
A a = new B(); 中的 a 是 A 类型,所以构造时会走 A 的构造方法 → 实际上仍执行 B(),且会先隐式调用 super() 到 A(),但这只是链式调用,不是多态调度NullPointerException 或默认值问题如果目标是“根据参数/条件创建不同子类实例”,应放弃让构造方法多态,改用设计模式:
Product
Product create(String type),内部用 if/else 或 Map 分发到具体子类的 new 调用Supplier 等函数式接口延迟构造public abstract class Shape {
public abstract void draw();
}
public class Circle extends Shape {
public Circle() { System.out.println("Circle constructed"); }
public void draw() { System.out.println("Drawing circle"); }
}
public class ShapeFactory {
public static Shape create(String type) {
return switch (type) {
case "circle" -> new Circle();
case "square" -> new Square();
default -> throw new IllegalArgumentException("Unknown type: " + type);
};
}
}
这是实际项目中最隐蔽的陷阱之一。看似“多态调用”,实则破坏初始化顺序:
class Parent {
String name;
Parent() {
init(); // ❌ 这里会调用 Child.init(),但 Child.name 还没赋值!
}
void init() { name = "parent"; }
}
class Child extends Parent {
String name = "child"; // 字段初始化在 super() 返回后才发生
void init() { name = "child-init"; } // 此时 this.name 是 null 或默认值
}
这种写法会导致 name 被设为 "child-init" 后又被字段初始化覆盖回 "child",或者更糟——如果 init() 里访问了未初始化的子类字段,直接抛空指针。
真正安全的做法:

initialize() 方法,并由使用者显式调用;或用 final 方法封死重写可能。