Java学习笔记之继承与初始化

在探讨包括继承在内的初始化全过程前,我们先总结下代码块的相关知识。

代码块

在java中,所谓的代码块,就是用大括弧{}将多行代码封装在一起,形成一个独立地数据体。Java中的代码块主要分为以下四种:普通代码块、静态代码块、构造代码块、同步代码块。

普通代码块

平常我们用的最多的就是普通代码块,它是在方法名后面用大括弧{}括起来的代码块。如:

1
2
3
4
5
public class Demo {
public void demo(){
System.out.println("普通代码块");
}
}

静态代码块

静态代码块就是用static关键词修饰的后面用大括弧{}括起来的代码块。主要用于对静态属性进行初始化。如:

1
2
3
4
5
public class Demo {
static{
System.out.println("静态代码块");
}
}

构造代码块

构造代码块,即在类中直接定义没有任何修饰符、前缀和后缀的代码块。如:

1
2
3
4
5
6
7
8
public class Demo {
public Demo (){
}

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

同步代码块

使用 synchronized 关键字修饰,并使用“{}”括起来的代码片段,它表示同一时间只能有一个线程进入到该方法块中,是一种多线程保护机制。

注意

  1. 静态代码块,其作用级别为类,构造代码块、构造函数,其作用级别为对象。
  2. 静态代码块,它是随着类的加载而被执行,只要类被加载了就会执行,而且只会加载一次,主要用于给类进行初始化。
  3. 构造代码块,每创建一个对象时就会执行一次,它依托于构造函数,但先于构造函数执行,主要用于初始化不同对象共性的初始化内容和初始化实例环境。
  4. 三者执行顺序为:静态代码块 > 构造代码块 > 构造函数

继承与初始化

可通过下面一个示例进行理解

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
public class HelloB extends HelloA {
public static void main(String[] args) {
new HelloB();
new HelloB(1);
}

/**
* 无参构造函数
*/

public HelloB()
{

System.out.println("无参构造函数 B");
}

/**
* 有参构造函数
*/

public HelloB(int x)
{

System.out.println("有参构造函数 B");
}

/**
* 构造代码块
*/

{
System.out.println("构造代码块 B");
}

/**
* 静态代码块
*/

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

class HelloA
{

/**
* 无参构造函数
*/

public HelloA()
{

System.out.println("无参构造函数 A");
}

/**
* 构造代码块
*/

{
System.out.println("构造代码块 A");
}

/**
* 静态代码块
*/

static
{
System.out.println("静态代码块 A");
}
}
/* 运行结果
静态代码块 A
静态代码块 B
构造代码块 A
无参构造函数 A
构造代码块 B
无参构造函数 B
构造代码块 A
无参构造函数 A
构造代码块 B
有参构造函数 B
*/

通过结果可以得知,当涉及到继承时,其执行顺序为:

  1. 初始化父类中的静态成员变量和静态代码块 ;
  2. 初始化子类中的静态成员变量和静态代码块 ;
  3. 初始化父类的普通成员变量和代码块,再执行父类的构造方法;
  4. 初始化子类的普通成员变量和代码块,再执行子类的构造方法;