Java中类的初始化顺序

初始化顺序

在类的内部,字段定义的先后顺序决定了初始化的顺序。即使字段定义散布于方法定义间,它们任旧会在任何方法(包括构造器)被调用前得到初始化。

  • 静态代码块,用static声明,jvm加载类时执行,仅执行一次
  • 构造代码块,类中用{}声明,每次创建对象时执行。
  • 构造函数 执行顺序:静态代码块,main(),构造代码块,构造函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Demo {
public Demo() {
System.out.println("构造方法");
}
static {
System.out.println("静态代码块");
}
{
System.out.println("构造代码块");
}
public static void main(String[] args) {

System.out.println("main()...");
new Demo();
}
}
/**out:
静态代码块
main()...
构造代码块
构造方法
*/

静态字段的初始化

静态字段用static修饰。注意static关键字不能应用于局部字段。

对于用static关键字修饰的字段,它的作用范围是整个类。可以用类名.静态字段/静态方法的方式来调用字段/方法。由此可见,静态字段只在第一次初始化类的时候才得到初始化。因为静态字段是对整个类起作用,无论创建多少个对象,静态字段/方法都只占用一份存储区域。如果一初始化类就重新给静态字段赋值,那么这个静态字段就和非静态字段没有区别了。

静态代码块

1
2
3
static { 

}

Java中允许将多个静态初始化动作组织成一个特殊的代码块,叫做静态代码块。

跟静态字段类似,静态代码块也是只在生成这个类的第一个对象时执行。也可以说,静态代码块是给对象初始化用的。

构造代码块

1
2
3
{

}

构造代码块的作用是给对象进行初始化。每个对象实例化时,都会调用这个类的构造代码块,它与构造函数的区别在于,每一个对象在创建时都要调用统一的构造代码块,而构造函数只给对应的对象初始化。

构造函数

1
2
3
4
5
6
7
8
public class Hello {

public Hello() {
}
public String hello() {
return "Hello world";
}
}

对象一旦建立,就会调用与之对应的构造函数,不建立对象,构造函数不会执行。构造函数的作用是给对象初始化。

对于静态变量、静态代码块、变量、构造代码块、构造函数,它们的初始化顺序依次是(静态变量、静态代码块)>(变量、构造代码块)>构造函数。

当涉及到继承时,按照如下顺序执行:

  • 执行父类的静态代码块,并初始化父类静态成员变量
  • 执行子类的静态代码块,并初始化子类静态成员变量
  • 执行父类的构造代码块,执行父类的构造函数,并初始化父类普通成员变量
  • 执行子类的构造代码块,执行子类的构造函数,并初始化子类普通成员变量
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


class Father {
static {
System.out.println("Father static");
}
{
System.out.println("Father {}");
}

public Father() {
System.out.println("Father father()");
}
}
public class Demo extends Father{
public Demo() {
System.out.println("构造方法");
}

static {
System.out.println("静态代码块");
}
{
System.out.println("构造代码块");
}

public static void main(String[] args) {

System.out.println("main()...");
new Demo();
}
}

/*out:
Father static
静态代码块
main()...
Father {}
Father father()
构造代码块
构造方法
*/
-------------本文结束感谢您的阅读-------------
0%