1. 程式人生 > >Java靜態變數的初始化分析

Java靜態變數的初始化分析

首先解釋下:
static關鍵字修飾變數
表示該類的所有物件共同擁有該屬性,相當於該類的全域性變數,類變數在載入的時候就初始化,而且只被初始化一次,程式中任何該類的物件對類變數做修改的時候,該類的其他物件得到的是修改之後的值,因此類量可以作為計數器,而且static變數可以用類名直接訪問不需要建立物件之後再訪問。
static修飾程式碼塊
static修飾類裡面獨立的程式碼塊,稱為靜態程式碼塊,靜態程式碼塊在第一次的時候執行,而且執行一次,由於靜態程式碼塊沒有名字,所以不能顯示的呼叫,只有在類載入的時候有虛擬機器去呼叫,主要完成一些初始化的操作。
static修飾方法
static修飾方法時,意味著所有物件擁有同一方法,static修飾的方法也是可以直接通過類名去呼叫,所以在靜態變數裡不能直接訪問非靜態物件和非靜態方法,在靜態方法中不能出現this,super等關鍵字。
類的載入:
在jvm第一次使用一個類的時候,會通過查詢classpath所指定的路徑,找到該類所對應的位元組碼,然後載入到jvm中儲存起來,這個過程就稱為類載入。
無論是static修飾的變數,方法,還是程式碼塊,類被載入之後就可以執行,都可以脫離物件執行,不用通過物件建立,用物件去執行。

java程式碼:Order.class

public class Order {
    static Shirt s1 = new Shirt();
    static Pants p2;
    Boot t3 = new Boot(10);

    void print() {
        t3.fun();
    }

    public static void main(String[] args) {
        System.out.println("Creating new Shirt() in main");
        new Shirt();
        System.out
.println("Creating new Shirt() in main"); Order od = new Order(); od.t3.fun(); Pants t4 = new Pants("aa", 1); } }

java程式碼:Boot.class

public class Boot {
    Boot(int marker) {
        System.out.println("Boot(" + marker + ")");
    }

    void fun() {
        System.out
.println("BootfunOk"); } }

java程式碼:Pants.class

public class Pants {
    Pants() {
        System.out.println("Pants()");
    }

    Pants(String a, int i) {
        this();
        System.out.println("PantsOk");
    }
}

java程式碼:Shirt.class

public class Shirt {
    Boot b1 = new Boot(1);
    /** 先static後非static變數初始化的順序原則開始初始化各個變數. */
    static Boot b2 = new Boot(2);

    Shirt() {
        System.out.println("Shirt()");
    }

    static Boot b3 = new Boot(3);
}

分析執行結果:
首先從public類開始執行,這時候會載入Order.class,
1,先執行 static Shirt s1 = new Shirt();
由於s1是一個物件的引用變數,首先會得到初始化,就會跳到Shirt的例項中按照先static後非static的變數初始化的順序開始初始化各個變數,
1.1,
在Shirt中順序:
靜態變數
static Boot b2 = new Boot(2);
static Boot b3 = new Boot(3);
非靜態變數
Boot b1 = new Boot(1);
變數初始化完成之後再執行Shirt的構造方法
1.2,
Shirt() {
System.out.println(“Shirt()”);
}
Shirt s1初始化完成之後再回到public類Order.class中
2,這是有static Pants p2;
由於p2只是宣告變數沒有建立物件讓它指向,因此接著執行下面的操作
3,發現static變數都初始化完成,那麼程式就轉如static方法中執行,也就是執行static的main方法,輸出:System.out.println(“Creating new Shirt() in main”);
注意:(Boot t3 = new Boot(10); 這一句為什麼得不到初始化,是因為此時沒有建立類Order的例項,所以程式目前還不會初始化該程式碼,至於以後會不會初始化,還要看在main方法中是否會建立Order類的例項,如建立了,則一定初始化,否則不會.)
4,接著就執行new Shirt();,也就是建立一個Shirt物件, **注意:**static變數的初始化,它只能初始化一次,也就是說,如果前面已經初始化過了,那麼此時就不必要再初始化了.
4.1,也就只會初始化非靜態變數 Boot b1 = new Boot(1);
4.2,變數初始化完成之後就執行構造方法
Shirt() {
System.out.println(“Shirt()”);
}
5,再回到main 方法中 輸出 System.out.println(“Creating new Shirt() in main”);
6,接著執行mian方法中的下一步Order od = new Order();
還是由於static變數的初始化,它只能初始化一次,所以建立Order物件時就只執行初始化非靜態變數 , 也就是建立非靜態物件 Boot t3 = new Boot(10);
7,接著執行mian方法,呼叫od.t3.fun();
8,最後執行main方法中的最後一句 Pants t4 = new Pants(“aa”, 1);
8.1,執行pants的兩個引數的構造方法時,會呼叫this(),所以依然會呼叫無引數的構造方法,所以先執行無引數的構造。
Pants() {
System.out.println(“Pants()”);
}
8.2,然後再是兩個引數的構造方法
Pants(String a, int i) {
System.out.println(“PantsOk”);
}

執行輸出結果是:
這裡寫圖片描述