引言
对于Java的初学者而言,很多时候我们只知道如何写一些基础的代码,但是却不知道为什么,对于一些概念而言,更是停留在一个很模糊的概念上,其实这样是不好的一种学习习惯。所以对于不太清楚的一些概念,自己多敲一敲,或许能更好的掌握。
问题
今天要说的问题是,Java中代码的执行顺序,不知道叫这个题目合适不。这里先定义几个类别:
- 构造方法(如:
public className(){……}) - 静态代码块(如:
static {……}) - 类的属性变量(如:
ClassA a = new ClassA())
这些它们在类被初始化时执行的顺序时怎么样的呢?
代码
- 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
- 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
上面的代码中,因为几个类都要在Main方法中运行,因此就声明为static类型了,这个大家都知道的吧,不声明为static时,编译器会报错:No enclosing instance of type ClassName is accessible.
主要使用了四个静态内部类。代码比较简答,就不作过多的说明了。
运行结果
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
结果分析
所以可以得出结论:
开始父类静态代码块(只执行一次)子类静态代码块(只执行一次)父类的属性类的静态代码块(只执行一次)父类属性类的构造函数父类的构造函数子类属性的静态代码块(只执行一次)子类属性类的构造函数子类的构造函数结束
//总结类的执行顺序
/**
* 开始
* 父类静态代码块(只执行一次)
* 子类静态代码块(只执行一次)
* 父类的属性类的静态代码块(只执行一次)
* 父类属性类的构造函数
* 父类的构造函数
* 子类属性的静态代码块(只执行一次)
* 子类属性类的构造函数
* 子类的构造函数
* 结束
*/
我们看main函数中的语句:
- 1
- 1
首先,Java是先初始化类B,初识化的过程中先初始化B的父类,再初始化B本身,因为静态代码块是在类
初始化的时候加载,而类只初识化一次。
初始化完B的时候:也就是执行B b执行完成。
程序打印出:
- 1
- 2
- 3
- 1
- 2
- 3
接下来,执行new B();
这个过程程序会先走到B的构造方法,如果B存在父类,则向上到父类的构造方法,也就是A的构造方法,此时会对A的属性类进行初始化,即
- 1
- 1
就会对C进行相应的初始化、实例化的一些过程,如果只是类的属性类的声明,如:
- 1
- 1
则不对类C进行初始化,更不会实例化。
因此按文章的代码,程序会打印出:
- 1
- 2
- 1
- 2
完成之后,就开始执行A的构造方法,程序会打印出:
- 1
- 1
父类完成之后,就开始对子类的属性初始化,以及属性构造方法调用,最后完成子类的实例化。
依此打印出:
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
ps:如果将A中的C c=new C();更改为static {C c;}系统也会先执行static代码块,只是,C c只对类C做了声明,因此这里也不会对C做初始化工作
本文通过具体示例详细解析了Java中类初始化的顺序,包括静态代码块、构造方法及属性变量的执行流程。
2370

被折叠的 条评论
为什么被折叠?



