社交媒体

构造方法

构造方法

钩子

上篇末尾留了个悬念:new 的第 2 步"执行初始化"到底是什么?

先看一个真实痛点:用上篇的写法,造一个学生要三行——new、赋 name、赋 age。造 100 个学生就是 300 行,而且谁都有可能忘了赋值,于是"我叫null"满天飞。

能不能让对象一出生就把名字带好?能,这就是构造方法——对象的出生证明。

01 构造方法:长得很怪,但很有用

class Student {
    String name;
    int age;

    // 构造方法:名字 = 类名,没有返回值
    Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    void introduce() {
        System.out.println("我叫" + name + ",今年" + age + "岁");
    }
}

三个特征,缺一不可:

  1. 方法名和类名一模一样(包括大小写);
  2. 不写返回值类型——连 void 都不写,写了就不是构造方法(上一篇的问题①的坑);
  3. new 的时候自动执行,你调不了它,它只在出生那一刻跑一次。
Student s1 = new Student("张三", 20);   // 出生即带名字,一行搞定
s1.introduce();   // 我叫张三,今年20岁

15-构造方法执行时机图.png

02 编译器偷偷送的那个构造方法

现在有个诡异的问题:第 14 篇我们明明没写任何构造方法,为什么 new Student() 也能编译通过?

因为编译器看你一张构造方法都没写,会偷偷送一个:Student() { }——空的、不干活的,专业名叫默认构造方法。

但注意"一张都没写"这个前提。一旦你自己写了任何一个构造方法,比如 Student(String name),编译器立刻收回赠送——这时 new Student() 直接编译报错:

错误: 无法将类 Student中的构造器 Student应用到给定类型;
  需要: java.lang.String
  找到:    没有参数

人话:图纸上的出生方式只有"带名字"一种,你却想无参出生,没有这种出厂设置。

这是新手高频报错,解法也简单:想让两种出生方式都可用,就都写出来——

03 构造方法也能重载

第 11 篇学的重载,在构造方法上照常生效:

Student() {                    // 无参出生:默认值
}

Student(String name) {         // 只带名字
    this.name = name;
}

Student(String name, int age) { // 带名字带年龄
    this.name = name;
    this.age = age;
}

三种构造方法,三种出生姿势,new 时传什么参数就命中哪个——和普通方法重载的匹配规则一模一样。

细心的话你会发现一个重复:每个构造方法里都在写 this.name = name。能不能只写一遍?能——答案就是下篇的主角 this,还顺便解锁 Java 的"链式调用"。


本文示例代码均已本地实测通过,可直接运行。
对应文件:ConstructorDemo.java


橙码酱,分享更有用的技术知识,助你成为更优秀的开发者。