JAVA初始化顺序

Posted by ShiYu on 2017-07-01

java在初始化类时,成员变量、静态变量、构造器的执行顺序是什么?涉及到继承时,它们的执行顺序又是什么?

测试一:

当不涉及继承时,执行顺序测试:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class App
{
A a1=new A("普通变量1");
static A a2=new A("静态变量1");
A a3=new A("普通变量2");
static A a4=new A("静态变量2");

public App(){
A a5=new A("构造器");
}

public static void main( String[] args )
{

new App();
}
}

class A{
public A(String msg){
System.out.println(msg);
}
}

输出结果


1
2
3
4
5
静态变量1
静态变量2
普通变量1
普通变量2
构造器

结论:


  1. 先按照静态变量到声明顺序依次执行
  2. 然后按照普通变量的声明顺序一次执行
  3. 最后执行构造器

测试二

当涉及到继承时,执行顺序测试


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
package top.shixiaoyu;

/**
* Hello world!
*/
public class App {


public static void main(String[] args) {

new B();
}
}

class A {
int i=1;
C c=new C("基类A中普通变量1");
static C c2=new C("基类A中静态变量1");
C c1=new C("基类A中普通变量2");
static C c3=new C("基类A中静态变量2");

public void play() {

System.out.println("基类A的paly中i的值是:" + i);
}

public A() {
System.out.println("这是基类A");
play();
}

}

class B extends A {
int i = 2;
C c=new C("导出类A中普通变量1");
static C c2=new C("导出类A中静态变量1");
C c1=new C("导出类A中普通变量2");
static C c3=new C("导出类A中静态变量2");
public void play() {
System.out.println("导出类的play中i的值是:" + i);
}

public B() {
play();
}
}

class C{
public C(String msg){
System.out.println(msg);
}
}

输出结果


1
2
3
4
5
6
7
8
9
10
11
基类A中静态变量1
基类A中静态变量2
导出类A中静态变量1
导出类A中静态变量2
基类A中普通变量1
基类A中普通变量2
这是基类A
导出类的play中i的值是:0
导出类A中普通变量1
导出类A中普通变量2
导出类的play中i的值是:2

结论:


  1. 首先初始化基类中的静态变量
  2. 然后初始化导出类中的静态变量
  3. 紧接着初始化基类中的普通变量
  4. 然后执行基类的构造器,此时play方法被导出类覆盖,所以执行的是导出类中被重写的play方法,但是我们发现,打印的i值并不是导出类的2,这是因为类在初始化的第一步是将所有对象分配的空间的值初始化成二进制的0,此时导出类中的基本变量i尚未初始化,而是初始化前的默认0,所以此处被覆盖的play方法打印的是0
  5. 然后初始化导出类的普通变量
  6. 最后执行导出类的构造函数,此时普通变量i已经初始化成2,所以此处打印的i值是2

总结:

java类初始化顺序如下:

  1. 将为所有对象分配的空间的值置为二进制的0
  2. 初始化基类的静态变量
  3. 初始化导出类静态变量
  4. 初始化基类普通变量
  5. 初始化基类构造器
  6. 初始化导出类普通变量
  7. 初始化导出类构造函数

|