Java類的加載過程以及單例模式的簡單解析

代碼寫了很多年了,一直有碌碌無爲的感覺。相信很多工作三四年的人都會和我有一樣的想法,覺得這樣子的狀態就是老油條的寫照,但是卻不知道其他的出路,總想打破現在的這個狀態,但是不知道如何下手。但是,告訴你們,其實我也不知道該怎麼下手。爲了打破這個寧靜,給自己找點事情做,於是,決定從基礎再重新學習一遍,順便帶着我家的懶婆娘學習。
牛逼的人直接跳過,這是給那些一知半解的人看到的。我知道很多人一看,心裏只有一個想法:這都是大家都知道的事情,類的加載無非就是幾個過程。確實,如果都懂的人,請自行繞過,因爲這確實很基礎,爲了突出這個不同的地方,所以我把單例模式的構建特點也一起分析。之前在華爲外包面試的就被問到的一個問題就是單模式,當時並不知道其中的原理,因爲我告訴面試官,不懂的就網上看,至於原理,確實不知道,於是,基於華爲的狼性文化,不錄用,吐槽一句:尼瑪這是外包,搞的正式員工一樣。
回到正題,Java虛擬機的類加載過程主要有七個步驟:Loading、verification、preparation、resolution、initialization、using、unloading。翻譯中文就是:加載,驗證,準備,解析,初始化,使用和卸載。具體的可以參考很早之前就有人寫的博客:http://www.importnew.com/18548.html。這篇博文裏面主要從使用方面講解,JVM的加載很有必要知道,不然哪怕是堆棧溢出的異常都不知道怎麼回事。
類的加載,首先會加載靜態的東西:靜態代碼塊,靜態屬性和靜態方法,這些是全局的,但是靜態的方法會初始化,但是不調用的話是不會執行的。靜態變量,比如:
private static int temp=1;  
    類加載的時候,定義的是str = 0,只有初始化完成之後,纔會給str複製1,而很多類似的靜態是按照程序順序進行加載的。初始化是JVM類加載的最後一步,靜態的其實就是相當於C語言的全局變量,Java稱之爲類變量。靜態變量是全局存在的,有點人直接new一個對象來引用靜態變量,以爲這樣可以防止內存消耗的問題,其實是一樣的,類引用和實例引用,只不過是一個親自引用,一個是代言人去引用,結果都是把靜態方法拉出放在程序裏面。那麼加載完靜態的,那麼初步的類加載就完成了,這特麼說的也太簡單了吧,其實大家可以去看看牛人說的具體機制,我水平有限,說錯了就耽誤大家了。接下來是不是該詢問:非靜態的方法,變量,以及代碼塊呢?這些,都是實例化的引用,如果你不new的話,代碼塊也是不會執行的,new 的時候,代碼塊是最先執行的,其次纔是父類的構造方法,再次纔是自身的構造方法,卸載銷燬就剛好想法,兒子先掛,老子最後掛,因爲將還是老的辣!
接下來就是進入主題了,單例模式的實現有餓漢式,懶漢式,具體的實現看我的上一篇博客,有介紹的。如果沒有併發的編程,餓漢式是最簡單粗暴的,還很容易記住。我開始就是使用餓漢式的,熟悉,但是多次的跳槽爲了應付面試,還是要腦補懶漢式以及DCL機制等等。除了這幾種,我主要是推薦的內部靜態類實現單例模式,具體寫法直接看代碼:
public class Singleton {

    private Singleton() {
    }

    public static Singleton getSingleInstance() {
        return SingletonHolder.sInstance;
    }

    private static class SingletonHolder{
        private static Singleton sInstance = new Singleton();
    }
}
本人上篇博客其實已經有詳細的說明,但是沒有設計到類的加載,所以借這個機會就再次說明下單例模式,因爲這個模式的使用範圍實在是太廣了額,很多面試官有特別喜歡問,當然,還要具備能夠白板寫出來的能力才行,不是看看就完了的。
那麼就這基礎的東西來分析一下,爲什麼DCL不能完全做到線程安全,而這個就可以呢。看上面對類的加載以及初始化的過程。靜態的只會在類首次的時候加載一次,內部類其實可以看作是類的一個屬性,所以可以輕鬆的訪問外部類的屬性和方法,在類第一次加載的時候,靜態的內部類就一直在並且不會進行二次加載,注意一點,final修飾的常量,或者放在常量池裏面的常量,是準備階段就已經賦值了,對,沒看錯,是在初始化之前的準備階段就已經有值了,所以常量顯示的速度是很快的。實例化的時候,虛擬機纔會加載SingletonHolder這個類,只有被調用的時候纔會初始化sInstance,也做到了延時的功能,懶漢式的作用就是如此,但是高併發的環境下,即使是DCL還是會有問題。這樣就實現了線程安全,並且知道爲什麼吧!最後說明一點,這篇博文重點是在說明類的加載這個很簡單,僅僅是藉助這個例子來說明而已,但是Android面試經常問到的問題。不要吐槽太簡單,那是因爲小夥伴們懂的實在是太多了!
如果有說錯的地方,希望指出,一起交流,謝謝!

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