Menu

Java 构造方法:用 new 初始化对象

Java 构造方法的工作原理:默认构造方法、带参数的构造方法、this、构造方法重载,以及用 this() 和 super() 链式调用。

本页包含可运行的编辑器。编辑、运行,立即查看输出。

为什么需要构造方法

上一页你创建了类,并用 new 创建了对象。构造方法就是在 new 调用期间真正运行的代码。它唯一的目的是交回一个可以直接使用的对象:所有必需的字段都已设置,没有初始化到一半的状态。

构造方法看起来像方法,但有两点不同:它与类同名,并且没有返回类型,连 void 都没有。

new Point(3, 4) 先分配对象,然后以 x = 3 和 y = 4 运行构造方法体。到 new 返回时,p 已经完全初始化好了。

this 关键字

在上面的构造方法中,参数名是 x 和 y,与字段同名。this.x 表示“这个对象的字段 x”,而单独的 x 指的是参数。没有 this,x = x 只会把参数赋给它自己,字段保持不变。

只有当参数遮蔽了字段时才必须写 this,但很多人为了清晰到处都写。常见的错误是名字冲突时忘了写它:代码能编译、能运行,却悄悄让字段保持默认值(null、0、false)。

默认构造方法

如果你从没写过构造方法,Java 会悄悄提供一个默认构造方法:一个公有的、无参数的、不做任何额外事情的构造方法。这就是为什么在完全没有构造方法的类上也能使用 new。

问题在于:只要你写了任何一个构造方法,这个免费的就没有了。

class Box {
    int size;

    Box(int size) {       // now there is NO no-arg constructor
        this.size = size;
    }
}

new Box();   // compile error: no constructor Box() exists

如果你仍希望 new Box() 能用,就自己声明无参构造方法:

构造方法重载

一个类可以有多个构造方法,只要它们的参数列表不同。这其实就是把方法重载用在了构造方法上。每个构造方法都提供了一种创建对象的不同方式。

Java 会根据你传给 new 的参数个数和类型,选择匹配的构造方法。

用 this() 链式调用

注意上面的重复:每个构造方法都自己给字段赋值。你可以让一个构造方法用 this(...) 调用另一个,从而避免重复。这个调用必须是构造方法中的第一条语句。

现在真正的初始化只集中在一处。较简单的构造方法只是填上默认值,再把工作转交出去。如果你试图在 this(...) 之前放一条语句,编译器会拒绝。

构造方法与 super()

每个构造方法都会先隐式调用父类的构造方法。如果你什么都不写,Java 会在方法体开头插入一个隐藏的 super()(父类的无参构造方法)。等你开始编写子类时,就会直接用到它,这也是下一个主题。

class Animal {
    String name;
    Animal(String name) { this.name = name; }
}

class Dog extends Animal {
    Dog(String name) {
        super(name);   // must call the parent constructor explicitly here
    }
}

因为 Animal 没有无参构造方法,Dog 必须显式调用 super(name):没有免费的 super() 可以兜底。和 this() 一样,super(...) 调用也必须是构造方法中的第一条语句。

下一步:继承

构造方法负责初始化单个对象,但 super() 已经暗示了更大的东西:类可以建立在其他类之上,复用它们的字段、方法和构造方法。这种一个类扩展另一个类的关系就是继承,也就是下一页的内容。

常见问题

Java 中的构造方法是什么?

构造方法是一种特殊的方法,在你用 new 创建对象时运行。它和类同名,没有返回类型(连 void 都没有)。它的任务是让新对象处于有效的初始状态,通常是把构造方法的参数赋给对象的字段。

Java 中构造方法和普通方法有什么区别?

构造方法与类的名字完全相同,不声明返回类型,而且只能在创建对象时通过 new 调用。普通方法有自己的名字,声明返回类型(或 void),在已有的对象上调用。构造方法负责初始化,普通方法负责之后的工作。

如果我不写构造方法会怎样?

编译器会免费给你一个默认构造方法:它不接收参数,除了隐式的 super() 调用之外什么也不做。但只要你自己写了任何一个构造方法,这个免费的就会消失。所以如果你添加了带参数的构造方法,又仍希望 new Thing() 能用,就必须显式声明无参构造方法。

Coddy 编程语言插图

和 Coddy 一起学编程

开始