用一张GIF理解“Java子类实例化总是默认调用父类的无参构造方法”

之前学基础的时候记得继承类继承父类所有非private的变量和方法,另外Java子类实例总是默认调用父类的无参构造方法,但认识不深刻,所以这次直接自己写一个父类和子类,直接单步调试一下。

实现代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
// 父类
class Father {
// 姓氏
private String lastName = "张";
// 门牌号
private int roomNumber = 405;

// 共有方法
public String getLastName() {
return lastName;
}

// 私有方法
private int getRoomNumber() {
return roomNumber;
}

public Father() {
System.out.println("父类 无参构造函数 父类的姓氏:" + lastName + ",门牌号:" + roomNumber);
}

public Father(String lastName, int roomNumber) {
this.lastName = lastName;
this.roomNumber = roomNumber;
System.out.println("父类 2个参数的参构造函数 父类的姓氏:" + lastName + ",门牌号:" + roomNumber);
}
}

// 子类
class Child extends Father {
// 兴趣爱好
private String hobbies;
// 从事工作
private String job;

public String getHobbies() {
return hobbies;
}

public String getJob() {
return job;
}

public Child() {
System.out.println("子类 无参数的构造函数 儿子兴趣爱好:" + hobbies + ",从事工作:" + job);
}

public Child(String hobbies, String job) {
this.hobbies = hobbies;
this.job = job;
System.out.println("子类 2个参数的构造函数 儿子兴趣爱好:" + hobbies + ",从事工作:" + job);
}

public Child(String lastName, int roomNumber, String hobbies, String job) {
super(lastName, roomNumber);
this.hobbies = hobbies;
this.job = job;
System.out.println("子类 使用super()带4个参数的构造函数 儿子兴趣爱好:" + hobbies + ",从事工作:" + job);
}
}

class Test {
public static void main(String[] args) {
System.out.println("大儿子:");
Child bigSon = new Child();
System.out.println("大儿子姓氏:" + bigSon.getLastName());
System.out.println("---------------------------");

System.out.println("二儿子:");
Child secondSon = new Child("桌球", "律师");
System.out.println("二儿子姓氏:" + secondSon.getLastName() + ",爱好:"+secondSon.getHobbies()+",工作:"+secondSon.getJob());
System.out.println("---------------------------");

System.out.println("小儿子:");
Child littleSon = new Child("李", 306, "足球", "医生");
System.out.println("小儿子姓氏:" + littleSon.getLastName() + ",爱好:"+littleSon.getHobbies()+",工作:"+littleSon.getJob());
}
}

运行结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
大儿子:
父类 无参构造函数 父类的姓氏:张,门牌号:405
子类 无参数的构造函数 儿子兴趣爱好:null,从事工作:null
大儿子姓氏:张
---------------------------
二儿子:
父类 无参构造函数 父类的姓氏:张,门牌号:405
子类 2个参数的构造函数 儿子兴趣爱好:桌球,从事工作:律师
二儿子姓氏:张,爱好:桌球,工作:律师
---------------------------
小儿子:
父类 2个参数的参构造函数 父类的姓氏:李,门牌号:306
子类 使用super()带4个参数的构造函数 儿子兴趣爱好:足球,从事工作:医生
小儿子姓氏:李,爱好:足球,工作:医生

Process finished with exit code 0

单步调试

调试断点加在:18行,22行,44行,=48行,54行,64行
调试结果GIF

总结

  1. 从运行结果可以看出,尽管子类并没有给姓氏赋值,但依然打印出了姓氏:李,说明子类可以调用到父类非private的方法。
  2. 从GIF中的调试结果可以看出,每次子类的实例在初始化时,不论子类实例化时是否带由参数都将进入父类无参构造函数。当且仅当子类构造方法使用super()方法时,会进入父类相应的有参构造函数。
  3. 最后还可以从GIF中发现,非static成员变量的执行顺序在构造函数之前。
码哥 wechat
欢迎关注个人订阅号:「码上行动GO」