源本科技 | 码上会

Java 构造函数

2025/12/26
45
0

在 Java 中,构造函数(Constructor) 是创建对象时自动调用的特殊成员方法,用于初始化对象的状态。它是面向对象编程中确保对象“出生即可用”的关键机制。


学习目标

  • 理解构造函数的基本语法与作用

  • 掌握四种构造函数类型:默认、参数化、拷贝、私有

  • 学会使用构造函数重载实现灵活初始化

  • 了解私有构造函数在设计模式中的应用

  • 避免常见误区(如返回类型、调用时机等)


什么是构造函数

构造函数是类中一种特殊的方法,具有以下特征:

  • 名称必须与类名完全相同

  • 没有返回类型(连 void 也不允许)

  • 在使用 new 创建对象时自动调用

  • 可包含参数,用于初始化对象属性

基本构造函数

class Student {
    String name;
    int id;

    // 构造函数
    Student(String name, int id) {
        this.name = name;
        this.id = id;
    }
}

如果你写了一个带返回类型的“构造函数”,它就只是一个普通方法!


四种构造函数类型

默认构造函数

  • 无参数

  • 若类中未定义任何构造函数,Java 编译器会自动生成一个空的默认构造函数

  • 用于为对象字段赋予默认值(如 0nullfalse

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 创建实例

  • 常用于以下场景:

应用场景

说明

单例模式(Singleton)

确保整个程序只有一个实例

工具类

MathCollections,只提供静态方法

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(...) 实现构造链

  • 一旦定义了任意构造函数,默认构造函数不再自动生成


思考题

  1. 如果一个类继承了父类,创建子类对象时,父类和子类的构造函数调用顺序是怎样的?

  2. 为什么 Java 不提供内置的拷贝构造函数?这与它的内存模型有何关系?

  3. 在单例模式中,除了私有构造函数,还需要哪些机制来确保线程安全?