详解java中继承关系类加载顺序问题

2025-05-29 0 80

详解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
/**

* Created by fei on 2017/5/31.

*/

public class SonClass extends ParentClass{

public SonClass(){

System.out.println("SonClass's constructor");

}

{ System.out.println("SonClass's block");}

static {

System.out.println("SonClass's static block ");

}

public static void main(String[] args) {

System.out.println("------ main start ------ ");

new SonClass();

System.out.println("------ main end ------ ");

}

}

class ParentClass{

public ParentClass(){

System.out.println("ParentClass's constructor");

}

{ System.out.println("ParentClass's block");}

static {

System.out.println("ParentClass's static block ");

}

}

运行结果:

?

1

2

3

4

5

6

7

8
ParentClass's static block

SonClass's static block

------ main start ------

ParentClass's block

ParentClass's constructor

SonClass's block

SonClass's constructor

------ main end ------

根据运行结果,一目了然,在执行 main 方法中 new SonClass() 之前,就在类加载之后执行了类中 static 代码块。然后再进入main方法,执行new操作,当然显而易见,在执行new子类操作的时候,是要先进行其父类的构造,即先执行父类的构造代码块(代码中只用大括号包裹的那段代码)以及构造函数 ,然后再执行子类的构造代码块以及构造函数。

修改一下代码,再来看看运行的结果:

?

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
/**

* Created by fei on 2017/5/31.

*/

public class SonClass extends ParentClass{

ParentClass parentClass;

public SonClass(){

System.out.println("1");

}

public SonClass(String name){

System.out.println("2");

this.name = name;

parentClass = new ParentClass("FEI");

}

public static void main(String[] args) {

System.out.println("------ main start ------ ");

new SonClass("fei");

System.out.println("------ main end ------ ");

}

}

class ParentClass{

String name ;

public ParentClass(){

System.out.println("3");

}

public ParentClass(String name){

System.out.println("4");

this.name = name ;

}

}

运行的顺序是:

?

1

2

3

4

5
------ main start ------

3

2

4

------ main end ------

第一个规则:子类的构造过程中,必须调用其父类的构造方法。一个类,如果我们不写构造方法,那么编译器会帮我们加上一个默认的构造方法(就是没有参数的构造方法),但是如果你自己写了构造方法,那么编译器就不会给你添加了,所以有时候当你new一个子类对象的时候,肯定调用了子类的构造方法,但是如果在子类构造方法中我们并没有显示的调用基类的构造方法,如:super(); 这样就会调用父类没有参数的构造方法。

第二个规则:如果子类的构造方法中既没有显示的调用基类构造方法,而基类中又没有无参的构造方法,则编译出错,所以,通常我们需要显示的:super(参数列表),来调用父类有参数的构造函数,此时无参的构造函数就不会被调用。

总之,一句话:子类没有显示调用父类构造函数,不管子类构造函数是否带参数都默认调用父类无参的构造函数,若父类没有则编译出错。

还是两个类,我们再更改一下。

?

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
/**

* Created by fei on 2017/5/31.

*/

public class SonClass extends ParentClass{

private String name = "SonClass";

public SonClass() {

printName();

}

public void printName() {

System.out.println("SonClass print name: " + name);

}

public static void main(String[] args){

new SonClass();

}

}

class ParentClass{

private String name = "ParentClass";

public ParentClass() {

//System.out.println(this.getClass());

printName();

}

public void printName() {

System.out.println("ParentClass print name: " + name);

}

}

看了上面的两个例子,最后这个例子就很容易被迷惑,可能有人会觉得运行结果是类似这样的:

?

1

2
ParentClass print name: ParentClass

SonClass print name: SonClass

或者是:

?

1

2
ParentClass print name: SonClass

SonClass print name: SonClass

但真正的结果是这样的:

?

1

2
SonClass print name: null

SonClass print name: SonClass

为什么会这样,其实只要打开代码中父类构造器中的这句注释,就很容易理解了:System.out.println(this.getClass())
结果是:

?

1
class SonClass

没错,父类中的this引用是子类实例对象,所以在父类构造函数里调用的还是子类的printName()方法。具体原因也并我能十分肯定,我个人浅见,是因为虽然我们调用了父类的构造方法,但是我们并没有实例化出父类的实例对象,所以this还是指向的是子类的引用。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

原文链接:http://blog.csdn.net/zhangjunfei12103323/article/details/72821071

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 详解java中继承关系类加载顺序问题 https://www.kuaiidc.com/116229.html

相关文章

发表评论
暂无评论