java基礎-靜態,非靜態(構造)代碼塊,類加載

static block and non-static block(constructor block)

[toc]java

想來想去,先來一題比較好

public class Foo {
    public static void main(String[] args) {
        Baz.testAsserts();
        Baz.testAsserts();
        // Will execute after Baz is initialized.
    }
}

class Bar {
    static {
        Baz.testAsserts();
        // Will execute before Baz is initialized!
    }
}


class Baz extends Bar {
    static int x = 1;

    static void testAsserts() {

        System.out.println("x is " + x);
        x=x+2;
    }

}
  • 輸出結果
x is 0
x is 1
x is 3
  • 分析
  1. Invoking Baz.testAsserts() cause Baz to be initialized
  2. default value int x=0;
  3. Before Baz initialize , Bar must be initialized
  4. Bar's static initializer again invoking Baz.testAsserts()
  5. so x is 0 , then x+2 , x=2
  6. go on initializing Baz , init x = 1;
  7. Invoking Baz.testAsserts() x = 1 , so x is 1;

Java類初始化順序

父類靜態變量 ——>父類靜態代碼塊——>子類靜態代碼塊——>父類非靜態變量 ——>
父類非靜態代碼塊——>父類構造函數 ——>子類非靜態變量——>子類非靜態代碼塊——>
子類構造函數

非靜態代碼塊 non-static block(constructor block)

class A {

    int x ;

    //block num 1
    {
        x = 1;
        System.out.println("block num 1, x is " + x);
    }

    A() {
        x = 3;
        System.out.println("constructor block x is " + x);
    }

    //block num 2
    {
        x = 2;
        System.out.println("block num 2, x is " + x);
    }

}


public class Non_staticBlock {

    public static void main(String[] args) {

        String newLine = System.getProperty("line.separator");

        System.out.println("====first time instantiate ====" + newLine);
        new A();

        System.out.println(" \n====second time instantiate ====" + newLine);
        new A();
    }

}
  • 輸出結果、順序
====first time instantiate ====

block num 1, x is 1
block num 2, x is 2
constructor x is 3 jvm

====second time instantiate ==== 函數

block num 1, x is 1
block num 2, x is 2
constructor x is 3this

  • 非靜態代碼塊被java編譯器拷貝到了構造塊內,因此稱爲"constructor block"也是能夠的,因此每次 new 構造函數也都執行
  • .class 文件以下, 非靜態代碼塊被java編譯器拷貝到了構造塊內.
class A {
    int x = 1;

    A() {
        System.out.println("block num 1, x is " + this.x);
        this.x = 2;
        System.out.println("block num 2, x is " + this.x);
        this.x = 3;
        System.out.println("constructor x is " + this.x);
    }
}

靜態代碼塊 static block

class AA {

    AA() {
        x = 3;
        System.out.println("constructor x is " + x);
    }

    static int x = 1;

    //block num 1
    static {
        System.out.println("static block num 1 , x is " + x);
    }

    //block num 2
    static {
        x = 2;
        System.out.println("static block num 2 , x is " + x);
    }

    static void print() {
        System.out.println("static method");
    }
}


public class StaticBlock {
        static {
        System.out.println("==== first ====");
    }

    public static void main(String[] args) {
        String newLine = System.getProperty("line.separator");
        System.out.println("====AA class init ====" + newLine);
        // class init
        AA.print();
        
        System.out.println(" \n====fisrt time instantiate AA====" + newLine);
        
        new AA();
        System.out.println(" \n====sencond time instantiate AA====" + newLine);
        new AA();
    }
}
  • 輸出結果、順序
==== first ====
====AA class init ====

static block num 1 , x is 1
static block num 2 , x is 2
static method
==== first time instantiate AA ==== code

constructor x is 3 get

==== second time instantiate AA ==== 編譯器

constructor x is 3it

  • 因爲JVM在加載類時會執行靜態代碼塊,且只會執行一次. 本例靜態引用AA.print(); 觸發類初始化
  • 靜態代碼塊先於主方法執行,本例優先打印first
  • 更多內容搜索jvm類加載
  • .class 文件以下
class AA {
    static int x = 1;

    AA() {
        x = 3;
        System.out.println("constructor x is " + x);
    }

    static void print() {
        System.out.println("static method");
    }

    static {
        System.out.println("static block num 1 , x is " + x);
        x = 2;
        System.out.println("static block num 2 , x is " + x);
    }
}

聯合看一下

class AAA {
    int x;

    //block num 1
    {
        x = 1;
        System.out.println("non-static block num 1 x is " + x);
    }

    AAA() {
        x = 3;
        System.out.println("constructor x is " + x);

    }

    //block num 2
    {
        x = 2;
        System.out.println("non-static block num 2 x is " + x);
    }


    // The static block only gets called once,when the class itself is initialized,
    // no matter how many objects of that type you create
    static {
        System.out.println("static block");
    }


    //Gets called every time an instance of the  class is constructed.
    //the non-static block is actually copied by the Java compiler into every constructor the class has (source).
    //So it is still the constructor's job to initialize fields.
    //to understand "actually " , find the result in the .class file of A.class
    {
        System.out.println("non-static block");
    }
}


public class BlockSample {

    public static void main(String[] args) {

        String newLine = System.getProperty("line.separator");

        System.out.println("====first time instantiate AAA ====" + newLine);
        new AAA();

        System.out.println(" \n====second time instantiate AAA ====" + newLine);
        new AAA();

    }
}
  • 輸出結果、順序
====first time instantiate AAA ====

static block
non-static block num 1 x is 1
non-static block num 2 x is 2
non-static block
constructor x is 3 編譯

====second time instantiate AAA ==== class

non-static block num 1 x is 1
non-static block num 2 x is 2
non-static block
constructor x is 3

  • .class 文件
class AAA {
    int x = 1;

    AAA() {
        System.out.println("non-static block num 1 x is " + this.x);
        this.x = 2;
        System.out.println("non-static block num 2 x is " + this.x);
        System.out.println("non-static block");
        this.x = 3;
        System.out.println("constructor x is " + this.x);
    }

    static {
        System.out.println("static block");
    }
}
相關文章
相關標籤/搜索