1. 程式人生 > >Java雙括號初始化——匿名內部類

Java雙括號初始化——匿名內部類

http://blog.csdn.net/congduan/article/details/49804013

2015-11-12 19:58

常用的初始化方式

Java中可以使用括號進行初始化,並且分為靜態程式碼塊和非靜態程式碼塊。如下:

public class Test {
    public static int num = 0;
    String s = ""; 

    {
        s = "abc";
        System.out.println("non static init");
    }

    static {
        num = 1;
        System.out.println("static init"
); } public void runTest(){ System.out.println(num); System.out.println(s); } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

執行Test類的runTest方法,輸出如下:

static init 
non static init 

abc

從輸出結果可以看出,有static修飾的靜態程式碼塊在非靜態程式碼塊之前執行。

另外,非靜態程式碼塊與靜態程式碼塊有個區別: 
靜態程式碼塊,在虛擬機器載入類的時候就會載入執行,而且只執行一次; 
非靜態程式碼塊,在建立物件的時候(即new一個物件的時候)執行,每次建立物件都會執行一次。

為了驗證以上區別,寫測試程式如下:

Test test1 = new Test();
Test1.runTest();
Test test2 = new Test();
test2.runTest();
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

輸出結果如下:

static init 
non static init 

abc 
non static init 

abc

驗證確實靜態程式碼塊只執行一次,非靜態程式碼塊每次建立都執行。

初始化的形式

除了以上的程式碼塊方式進行初始化,Java中還有一種初始化方式,即雙括號初始化。形式如下:

    Test test = new Test(){
        {
            num = 2
; s = "aaa"; } }; test.runTest();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

這樣輸出結果為:

static init 
non static init 

aaa

這種初始化方式實際上是利用了匿名類的特性。外層的括號其實是建立了一個匿名的內部類,而內層的括號是匿名類的建構函式,所以可以直接插入初始化程式碼。

如果我們在內部建構函式和括號形式的建構函式中分別列印一條資訊,可以得到如下結果:

static init 
non static init 
inner constructor 
brackets constructor 

aaa

括號中的程式碼晚於內部建構函式執行。

有什麼利弊

儘管雙括號初始化方式讓程式設計的可讀性變得簡單,但是因為要建立一個匿名的內部類,匿名內部類會持有外部類的引用,有造成記憶體洩露的風險