Skip to content

构造方法

概述

构造方法(Constructor)是类中用于初始化对象的一种特殊方法:在通过 new 创建对象时,JVM 会自动调用对应类中的构造方法,从而在对象「诞生」时就完成成员变量的赋值或其它初始化逻辑。构造方法的方法名必须与类名完全相同,且没有返回值类型(连 void 也不写)。

理解构造方法,可以避免对象创建后成员变量处于默认值或 null 的不可控状态,是 类与对象 之后、封装继承 的重要基础。

前置建议

已掌握 类与对象,理解 new 类名() 创建对象及成员变量的访问。


基本语法

构造方法的定义规则

  • 方法名:必须与类名完全一致(大小写一致)。
  • 无返回值:不能写 void 或其它返回类型;若写了返回类型,就变成普通方法而非构造方法。
  • 修饰符:可以是 publicprotectedprivate 或默认(包私有),通常使用 public
  • 参数:可以有零个或多个参数,与普通方法一样支持重载。

基本格式

java
// 无参构造方法
public 类名() {
    // 初始化逻辑,可为空
}

// 有参构造方法
public 类名(参数类型1 参数1, 参数类型2 参数2, ...) {
    // 通常用参数为成员变量赋值
}

使用示例

示例 1:无参构造与有参构造

无参构造方法在 new 类名() 时被调用,有参构造方法在 new 类名(实参...) 时被调用;可根据需要为类提供多种构造方法(重载)。

java
public class Person {
    String name;
    int age;

    // 无参构造:创建对象时给成员变量设默认值
    public Person() {
        name = "未命名";
        age = 0;
    }

    // 有参构造:创建对象时直接传入 name 和 age
    public Person(String name, int age) {
        this.name = name;   // this 表示当前对象,见下文
        this.age = age;
    }

    void sayHello() {
        System.out.println("Hello, I'm " + name + ", " + age + " years old.");
    }
}

// 使用
Person p1 = new Person();              // 调用无参构造,name="未命名", age=0
Person p2 = new Person("张三", 20);    // 调用有参构造,name="张三", age=20
p1.sayHello();   // Hello, I'm 未命名, 0 years old.
p2.sayHello();   // Hello, I'm 张三, 20 years old.

提示

有参构造中常用 this.成员变量 = 参数 区分参数与成员变量(参数名与成员变量同名时,不加 this 的为参数)。this 表示「当前对象」,详见后续封装与多态章节。

示例 2:默认构造方法

若类中没有显式定义任何构造方法,编译器会自动提供一个无参的默认构造方法(即 public 类名() { }),因此可以写 new Person()。一旦类中定义了任意一个构造方法(无论有参无参),编译器就不再自动提供默认无参构造方法。

java
public class Book {
    String title;
    String author;

    // 只定义了有参构造
    public Book(String title, String author) {
        this.title = title;
        this.author = author;
    }
}

// 可以这样用
Book b = new Book("Java 核心技术", "Cay S. Horstmann");

// 若取消下面注释,会编译错误:找不到无参构造方法
// Book b2 = new Book();

若希望既保留有参构造,又能无参创建对象,需要显式写出无参构造方法

java
public class Book {
    String title;
    String author;

    public Book() {
        title = "";
        author = "";
    }

    public Book(String title, String author) {
        this.title = title;
        this.author = author;
    }
}

注意

子类构造方法会隐式或显式调用父类构造方法。若父类只定义了有参构造、没有无参构造,子类必须通过 super(参数) 显式调用父类有参构造,否则编译报错。详见 继承

示例 3:构造方法重载与 this() 调用

一个类可以有多个构造方法(重载:方法名相同、参数列表不同)。在某个构造方法中,可以通过 this(参数列表) 调用本类的其它构造方法,从而避免重复代码;this(...) 必须写在构造方法体的第一行,且最多调用一次。

java
public class Rectangle {
    double width;
    double height;

    // 无参构造:默认 0x0
    public Rectangle() {
        this(0, 0);   // 调用本类两参构造,必须位于第一行
    }

    // 单参构造:正方形
    public Rectangle(double side) {
        this(side, side);   // 调用两参构造
    }

    // 两参构造:实际完成赋值
    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }

    double getArea() {
        return width * height;
    }
}

// 使用
Rectangle r1 = new Rectangle();        // 0x0,面积 0
Rectangle r2 = new Rectangle(5);       // 5x5 正方形,面积 25
Rectangle r3 = new Rectangle(3, 4);   // 3x4,面积 12

构造方法与 new 的关系

  • 执行 new 类名(实参) 时,JVM 会按实参类型和个数匹配类中对应的构造方法并执行。
  • 构造方法执行完毕,对象才完成创建,引用被赋给等号左侧的变量。
  • 构造方法不能像普通方法那样通过「对象.方法名()」主动调用,只能在 new 时由 JVM 调用(同一类内部可通过 this(实参) 间接调用本类其它构造方法)。

注意事项

  • 方法名与类名一致:若方法名与类名不同或写了返回类型,则变成普通方法,new 时不会调用,且可能失去「默认构造方法」。
  • 默认构造方法会消失:只要类中定义了任意一个构造方法,默认无参构造就不再自动生成;需要无参创建时务必显式写出无参构造。
  • this(…) 只能出现在构造方法中,且必须位于方法体第一行,不能与 super(…) 同时出现(子类构造方法中先通过 superthis 二选一调用,再写其它逻辑)。
  • 不要在构造方法中写过于复杂的逻辑或调用可能被重写的方法,否则在继承场景下可能导致未初始化完成就被子类重写方法访问,引发难以排查的问题。

提示

后续学习 封装与访问修饰符 时,常将成员变量设为 private,通过有参构造方法和 setter 方法赋值,既保证对象在创建时就有合理状态,又便于统一校验与维护。


相关链接

基于 VitePress 构建