在 java 語言中的類初始化塊 文章中我們簡單的介紹了下 java 中的實(shí)例初始化塊 ( iib )。不過我覺得介紹的有點(diǎn)簡單了,于是,再寫一篇文章詳細(xì)介紹下吧。
java 語言中,存在三種操作:方法 、構(gòu)造函數(shù) 和 初始化塊。
其中初始化塊又分為 實(shí)例初始化塊 ( iib ) 和 靜態(tài)初始化塊。本章節(jié),我們主要介紹實(shí)例初始化塊。
實(shí)例初始化塊 用于初始化實(shí)例變量。
實(shí)例初始化塊 會(huì)在初始化類的一個(gè)實(shí)例時(shí)執(zhí)行,而且在構(gòu)造函數(shù)之前就執(zhí)行。并且每次創(chuàng)建類的對象時(shí)它們都會(huì)執(zhí)行。
實(shí)例化塊的語法
實(shí)例初始化塊一般放在構(gòu)造函數(shù)之前,使用大括號 {} 擴(kuò)起來的代碼。語法結(jié)構(gòu)一般如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
class javatester { // 實(shí)例化塊 { system.out.println( "iib block" ); } // 構(gòu)造函數(shù) javatester() { system.out.println( "constructor called" ); } public static void main(string[] args) { javatester a = new javatester(); } } |
注意,實(shí)例化塊并不是類的必須。只是一個(gè)可選項(xiàng)。用于抽出構(gòu)造函數(shù)的公共部分單獨(dú)執(zhí)行而已。
這段代碼是可以編譯運(yùn)行的,運(yùn)行結(jié)果如下
1
2
3
|
[yufei @www .twle.cn java]$ javac javatester.java && java javatester iib block constructor called |
一個(gè)類中包含多個(gè)實(shí)例初始化塊
類中的 實(shí)例初始化塊 并不是類所必須的,而且,不限數(shù)量。一個(gè)類既可以沒有實(shí)例初始化塊,也可以有多個(gè)實(shí)例初始化塊。
如果一個(gè)類有多個(gè)實(shí)例初始化塊,那么它們會(huì)按照順序從上到下依次執(zhí)行,也就是說,定義在類頂部的實(shí)例初始化塊最先執(zhí)行。
我們來看一段代碼,下面的類 javatester 定義了多個(gè)實(shí)例初始化塊。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
class javatester { { system.out.println( "iib1 block 1 " ); } { system.out.println( "iib2 block 2" ); } javatester() { system.out.println( "constructor called" ); } { system.out.println( "iib3 block 3" ); } public static void main(string[] args) { javatester a = new javatester(); } } |
運(yùn)行上面這段代碼,輸出結(jié)果如下
1
2
3
4
5
|
[yufei @www .twle.cn java]$ javac javatester.java && java javatester iib1 block 1 iib2 block 2 iib3 block 3 constructor called |
父類中的初始化塊
在 java 語言的繼承體系中,父類同樣可以有初始化塊,而且數(shù)量不限。
父類的實(shí)例初始化塊在子類的構(gòu)造函數(shù)中調(diào)用 super() 之后立即運(yùn)行。編譯器會(huì)在執(zhí)行當(dāng)前類的實(shí)例初始化塊之前先執(zhí)行父類的實(shí)例初始化塊。
是不是很繞口,我們寫一段代碼來演示下
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
|
class b { b() { system.out.println( "b-constructor called" ); } { system.out.println( "b-iib block" ); } } public class javatester extends b { { system.out.println( "javatester iib1 block 1 " ); } { system.out.println( "javatester iib2 block 2" ); } javatester() { super (); system.out.println( "javatester-constructor called" ); } { system.out.println( "javatester iib3 block 3" ); } public static void main(string[] args) { javatester a = new javatester(); } } |
運(yùn)行以上范例,輸出結(jié)果如下
1
2
3
4
5
6
7
|
[yufei @www .twle.cn java]$ javac javatester.java && java javatester b-iib block b-constructor called javatester iib1 block 1 javatester iib2 block 2 javatester iib3 block 3 javatester-constructor called |
從運(yùn)行的結(jié)果來看,當(dāng)創(chuàng)建類 javatester 的對象時(shí),編譯器嘗試執(zhí)行類 javatester 的構(gòu)造函數(shù)。但因?yàn)樗幸粋€(gè)父類,在發(fā)現(xiàn)了 super() 語句后,就轉(zhuǎn)而先執(zhí)行父類的構(gòu)造函數(shù)。
因此,在繼承體系中,實(shí)例初始化塊和構(gòu)造函數(shù)的執(zhí)行順序如下
執(zhí)行父類的實(shí)例初始化塊
執(zhí)行父類的構(gòu)造函數(shù)
執(zhí)行當(dāng)前類的實(shí)例初始化塊
執(zhí)行當(dāng)前類的構(gòu)造函數(shù)
實(shí)例初始化塊的要點(diǎn)
我們一起來回顧下實(shí)例初始化塊的要點(diǎn)。
每次創(chuàng)建新實(shí)例時(shí)都會(huì)運(yùn)行實(shí)例初始化塊
初始化塊按它們在類中出現(xiàn)的順序運(yùn)行
如果存在父類,則首先會(huì)實(shí)例化父類然后在調(diào)用當(dāng)前類的實(shí)例初始化塊,最后再調(diào)用當(dāng)前類的構(gòu)造函數(shù)。