在 Java 中,构造函数(Constructor) 是创建对象时自动调用的特殊成员方法,用于初始化对象的状态。它是面向对象编程中确保对象“出生即可用”的关键机制。
理解构造函数的基本语法与作用
掌握四种构造函数类型:默认、参数化、拷贝、私有
学会使用构造函数重载实现灵活初始化
了解私有构造函数在设计模式中的应用
避免常见误区(如返回类型、调用时机等)
构造函数是类中一种特殊的方法,具有以下特征:
名称必须与类名完全相同
没有返回类型(连 void 也不允许)
在使用 new 创建对象时自动调用
可包含参数,用于初始化对象属性
基本构造函数
class Student {
String name;
int id;
// 构造函数
Student(String name, int id) {
this.name = name;
this.id = id;
}
}如果你写了一个带返回类型的“构造函数”,它就只是一个普通方法!

无参数
若类中未定义任何构造函数,Java 编译器会自动生成一个空的默认构造函数
用于为对象字段赋予默认值(如 0、null、false)
class CodeHub {
CodeHub() {
System.out.println("默认构造函数被调用");
}
public static void main(String[] args) {
CodeHub obj = new CodeHub(); // 输出:默认构造函数被调用
}
}
注意:一旦你定义了任意一个构造函数,编译器不再提供默认构造函数!
带有参数,用于按需初始化对象状态
是最常用的构造方式
class Developer {
String name;
int experience;
Developer(String name, int experience) {
this.name = name;
this.experience = experience;
}
void showInfo() {
System.out.println("开发者: " + name + ", 经验: " + experience + "年");
}
public static void main(String[] args) {
Developer dev = new Developer("李明", 5);
dev.showInfo(); // 输出:开发者: 李明, 经验: 5年
}
}
Java 不像 C++ 那样内置拷贝构造函数
需要手动编写:接受一个同类型对象作为参数,并复制其字段
class Product {
String name;
double price;
// 参数化构造函数
Product(String name, double price) {
this.name = name;
this.price = price;
}
// 拷贝构造函数
Product(Product other) {
this.name = other.name;
this.price = other.price;
}
public static void main(String[] args) {
Product p1 = new Product("笔记本电脑", 5999.0);
Product p2 = new Product(p1); // 使用拷贝构造函数
System.out.println("P1: " + p1.name + " - ¥" + p1.price);
System.out.println("P2: " + p2.name + " - ¥" + p2.price);
}
}P1: 笔记本电脑 - ¥5999.0
P2: 笔记本电脑 - ¥5999.0用途:创建对象副本,避免引用共享导致的数据污染。
使用 private 修饰,禁止外部通过 new 创建实例
常用于以下场景:
class StringUtils {
// 私有构造函数,防止实例化
private StringUtils() {
throw new UnsupportedOperationException("工具类不可实例化");
}
public static boolean isEmpty(String str) {
return str == null || str.trim().isEmpty();
}
}
public class Main {
public static void main(String[] args) {
// StringUtils s = new StringUtils(); // 编译错误!
System.out.println(StringUtils.isEmpty("")); // 正常调用静态方法
}
}同一个类中可以定义多个构造函数,只要它们的参数列表不同(数量、类型或顺序不同)。
这是方法重载的一种特例。
多版本构造函数
class User {
String name;
int age;
String email;
// 1. 只有名字
User(String name) {
this(name, 0); // 调用下一个构造函数
}
// 2. 名字 + 年龄
User(String name, int age) {
this(name, age, "unknown@example.com");
}
// 3. 全参数
User(String name, int age, String email) {
this.name = name;
this.age = age;
this.email = email;
}
void display() {
System.out.printf("用户: %s, 年龄: %d, 邮箱: %s%n", name, age, email);
}
public static void main(String[] args) {
new User("王芳").display();
new User("张伟", 28).display();
new User("李娜", 32, "lina@codehub.cn").display();
}
}输出:
用户: 王芳, 年龄: 0, 邮箱: unknown@example.com
用户: 张伟, 年龄: 28, 邮箱: unknown@example.com
用户: 李娜, 年龄: 32, 邮箱: lina@codehub.cn技巧:使用
this(...)在构造函数内部调用其他构造函数,避免代码重复(称为构造函数链)。
构造函数无返回类型,名称必须等于类名
支持重载,可通过 this(...) 实现构造链
一旦定义了任意构造函数,默认构造函数不再自动生成
如果一个类继承了父类,创建子类对象时,父类和子类的构造函数调用顺序是怎样的?
为什么 Java 不提供内置的拷贝构造函数?这与它的内存模型有何关系?
在单例模式中,除了私有构造函数,还需要哪些机制来确保线程安全?