想象一下,你为自己编写的每个类都创建了一个initialize()方法,方法名暗示了在使用类的对象之前,应该先调用它。这意味着用户必须记得主动调用此方法。在Java中,类的设计者可以通过编写构造器来确保每个对象的初始化。如果一个类有构造器,创建对象时Java就会自动调用它,此时用户还不能访问这个对象。这样就保证了初始化。
    接下来的挑战就是如何命名这个方法。这里有两个问题:第一,这个方法使用的任何名字都有可能与类里某个成员的名字相冲突;第二,编译器负责调用构造器,所以它必须始终知道应该调用哪个方法。C++语言采用的方案看起来最简单也最合乎逻辑,所以Java也采用了这个方案:构造器的名字就是类的名字。考虑到在初始化期间这个方法要被自动调用,这个方案看起来也就合情合理。
    下面是一个带有构造器的简单类:

    1. // housekeeping/SimpleConstructor.java
    2. // 一个简单构造器的演示
    3. class Rock {
    4. Rock() { // 这个就是构造器
    5. System.out.print("Rock ");
    6. }
    7. }
    8. public class SimpleConstructor {
    9. public static void main(String[] args) {
    10. for(int i = 0; i < 10; i++)
    11. new Rock();
    12. }
    13. }
    14. /* 输出:
    15. Rock Rock Rock Rock Rock Rock Rock Rock Rock Rock
    16. */

    当创建对象时:
    new Rock();
    给对象分配存储空间,然后调用这个类的构造器。构造器会保证这个对象在可用前就已经正确地初始化了。
    请注意,方法首字母小写的编程风格并不适用于构造器,因为构造器的名字必须与类的名字完全匹配。
    在C++中,不带参数的构造器叫作默认构造器(default constructor)。这个术语在Java出现之前就已经使用了很多年,但不知道出于什么原因,Java设计者决定使用术语无参构造器(no-arg constructor)。我觉得这很别扭,而且也没必要,所以我不愿意使用这个术语,而打算继续使用默认构造器。不过Java 8引入了default来作为方法定义的关键字,这可能会造成混淆。幸运的是,Java文档已经开始使用术语零参数构造器(zero-argument constructor)1

    1为符合中文术语惯例,后续仍翻译为无参构造器。——译者注

    和任何方法一样,构造器也可以传入参数来指定如何创建对象。前面的示例可以很容易地修改成让构造器接受一个参数:

    1. // housekeeping/SimpleConstructor2.java
    2. // 构造器可以有参数
    3. class Rock2 {
    4. Rock2(int i) {
    5. System.out.print("Rock " + i + " ");
    6. }
    7. }
    8. public class SimpleConstructor2 {
    9. public static void main(String[] args) {
    10. for(int i = 0; i < 8; i++)
    11. new Rock2(i);
    12. }
    13. }
    14. /* 输出:
    15. Rock 0 Rock 1 Rock 2 Rock 3 Rock 4 Rock 5 Rock 6 Rock 7
    16. */

    如果类Tree有一个构造器,它接受一个表示树高度的整数参数,你可以像这样创建一个Tree对象:
    Tree t = new Tree(12); // 12英尺的树(1英尺约合2.54厘米)
    如果Tree(int)是唯一的构造器,编译器就不会让你以任何其他方式创建Tree对象。
    构造器消除了初始化相关的很多问题,并使代码更易于阅读。例如,在前面的代码片段中,并没有对initialize()方法的显式调用,这种显式调用会在概念上分离初始化与创建。在Java中,创建和初始化是统一的概念,两者缺一不可。
    构造器是一类特殊的方法,它没有返回类型。这与返回类型为空(void)明显不同。对于空返回类型来说,方法不会返回任何内容,但这个方法的开发者还可以选择把返回类型定义为其他的(比如Integer或String)。而构造器没有返回类型,并且你也别无选择。注意new表达式确实返回了新建对象的引用。