關於Java裏static的一些思考

關於Java裏static的一些思考

Java Static


最近幫朋友做一個項目的時候想到了一個問題,那就是static到底是個什麼東西?結果在參考了網上的一些內容之後,發現了一些更有趣的東西。那就是java類被虛擬機加載時的加載順序。話不多說,先看一下下面這個經典的面試題例子。


public class Test {
    Person person = new Person("Test");
    static{
        System.out.println("test static");
    }

    public Test() {
        System.out.println("test constructor");
    }

    public static void main(String[] args) {
        new MyClass();
    }
}

class Person{
    static{
        System.out.println("person static");
    }
    public Person(String str) {
        System.out.println("person "+str);
    }
}


class MyClass extends Test {
    Person person = new Person("MyClass");
    static{
        System.out.println("myclass static");
    }

    public MyClass() {
        System.out.println("myclass constructor");
    }
}

我們可以看到,代碼並不算麻煩,那麼他到底哪裏有趣吸引了我呢?就是運行時的輸出結果:

test static
myclass static
person static
person Test
test constructor
person MyClass
myclass constructor

Process finished with exit code 0

也許有很多人會對這個輸出感到疑問。各位看官勿急,先看一下下面我總結的這兩張流程圖。這兩張圖基本能展示爲什麼會按照上面的輸出結果輸出。

規則流程圖1:含有public static void main方法的public類

Created with Raphaël 2.1.0準備加載含有main方法的A類A類是否有父類?加載A的父類加載A的靜態成員變量和靜態代碼塊加載main方法加載完畢yesno

規則流程圖2:不含有public static void main方法的類

Created with Raphaël 2.1.0準備加載A類A類是否繼承自B類加載B類的static靜態成員變量或者靜態代碼塊加載A類的靜態成員域和靜態成員方法初始化B類的成員變量執行A類的構造方法結束加載A類的靜態成員域和靜態成員方法執行A類的構造方法yesno

下面附上另一位大神對這道題的解釋:

類似地,我們還是來想一下這段代碼的具體執行過程。首先加載Test類,因此會執行Test類中的static塊。接着執行new MyClass(),而MyClass類還沒有被加載,因此需要加載MyClass類。在加載MyClass類的時候,發現MyClass類繼承自Test類,但是由於Test類已經被加載了,所以只需要加載MyClass類,那麼就會執行MyClass類的中的static塊。在加載完之後,就通過構造器來生成對象。而在生成對象的時候,必須先初始化父類的成員變量,因此會執行Test中的Person person = new Person(),而Person類還沒有被加載過,因此會先加載Person類並執行Person類中的static塊,接着執行父類的構造器,完成了父類的初始化,然後就來初始化自身了,因此會接着執行MyClass中的Person person = new Person(),最後執行MyClass的構造器。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章