單例有三種模式,懶漢式,餓漢式,和優化後的懶漢式
餓漢式單例模式:
餓漢式就像饑餓的人一樣先把事情都提前準備好,因為它是先在靜态屬性裡先提前建構好對象,然後再用靜态方法将對象傳回出去,是以會提前占用資源,但是速度比較快。例如:
<a href="https://s3.51cto.com/wyfs02/M02/08/D3/wKiom1nnjMvgm_ocAAwQYk4yAvM677.png" target="_blank"></a>
懶漢式單例模式:
懶漢式就像懶人一樣要等到事情來到面前了才開始做,因為它隻在靜态屬性裡聲明變量不建構對象,對象是在靜态方法裡經過判斷後才建構對象,但是在方法上要加synchronized同步鎖關鍵字,這個關鍵字是令通路排隊執行,如果不加這個關鍵字在多人調用的時候就會出現問題,會建構出多個對象,這樣就違背了單例模式的定義,懶漢式的優點在于不會提前占用資源,但是速度會慢得多。例如:
<a href="https://s1.51cto.com/wyfs02/M01/A7/83/wKioL1nnihuT1RNdAAsMKkO20ik871.png" target="_blank"></a>
優化後的懶漢式單例模式:
優化後的懶漢式也是在靜态屬性裡聲明變量不建構對象,在方法裡才開始建構對象,但是與原本的懶漢式不同的是,将同步鎖關鍵字寫在判斷語句内,先經過判斷條件再進行排隊建構對象,也就是先進入的進行排隊,後面再通路的就可以直接使用建構好的對象,不需要再進行排隊等待,進而優化了速度上的問題。例如:
<a href="https://s2.51cto.com/wyfs02/M00/08/D3/wKiom1nnjNrSAQ4uAAoh7R6WZPw145.png" target="_blank"></a>
其實這個方式就像平常家裡面一樣,大家一起在外面幹活,然後到飯點了,走的快的就先回到家做飯,走的慢的回到家就剛好可以吃飯了。這個代碼就是跑的快的先進行通路的去排隊建構對象,後面再通路的肯定就無法通過第一個判斷語句自然就可以直接使用return new好的對象。
Object祖先類(超類):
因為在java類的設計采用單根結構,即一個類隻能繼承一個類,是以在java中所有的類都是直接或間接繼承了Object類。Object類是比較特殊的類,它是所有類的父類,是java類層中最高類層。由于所有的類都是Object的子類,是以在定義類時,省略了extends關鍵字。例如:
<a href="https://s4.51cto.com/wyfs02/M02/A7/83/wKioL1nnii2S7CssAAuoTYrUWxo478.png" target="_blank"></a>
既然是父類自然也可以擁有Object類的方法,在Object類中主要包括clone()、finalize()、equals()、toString()、hashCode()等方法。
finalize()方法:
finalize()方法用于垃圾回收提醒,在java中還在被引用的對象不會被回收,沒有被引用或指向的是一個空指針,那麼這個對象就會被回收。例如:
<a href="https://s3.51cto.com/wyfs02/M01/08/D3/wKiom1nnjOihcCZrAAlRyH7PNOc054.png" target="_blank"></a>
此時在記憶體裡s1和s2由于指向的是空指針是以都會被垃圾回收機制回收掉。例如:
<a href="https://s2.51cto.com/wyfs02/M00/A7/83/wKioL1nnijexJjZwAAhBIQUcNxA220.png" target="_blank"></a>
如果還在被其他對象引用指向的就不會被回收。例如:
<a href="https://s5.51cto.com/wyfs02/M00/08/D3/wKiom1nnjPHS3qOLAAlJHy6mxoM237.png" target="_blank"></a>
此時s1還在被引用是以s1不會被回收。例如:
<a href="https://s2.51cto.com/wyfs02/M02/A7/83/wKioL1nnikOww4gUAAzanOd605g470.png" target="_blank"></a>
如果想要垃圾被回收的時候有個提醒就可以重寫Object的finalize()方法,這個方法是專門用來提醒垃圾回收的。例如:
<a href="https://s1.51cto.com/wyfs02/M02/08/D3/wKiom1nnjQLwRIAQABCOXRqf3YY706.png" target="_blank"></a>
因為s1還在被s3引用中,所有隻有s2會被回收
equals()方法:
因為在java中==是用來比較記憶體位址、對象的引用的,而equals方法是用于比較實際内容的。equals方法是Object類提供的比較方法,因為所有的類都預設繼承Object,這個方法用于比較本類對象和字元串内容是否相等。equals在String内的方法核心:
<a href="https://s1.51cto.com/wyfs02/M01/A7/83/wKioL1nnilaRiiVhAA_b4thzC5U267.png" target="_blank"></a>
這個方法的核心原理是先把要比較的對象作為參數傳遞進這個方法裡,然後先比較是否為目前對象,是的話就傳回true不是的話就繼續判斷這個對象是否為這個類的執行個體,是的話就将這個對象強制轉換為這個類的類型,接着比較長度是否一緻,長度不一緻就return false,長度一緻的話就把值一個個的拿出來比較,如果有一個值不一樣的話就會return false。
在java中字元串其實都是char數組,是以java有字元串池來優化字元串,使其不會占用太多的資源,因為字元串池的原因聲明指派時是同一個值就指向的是同一個記憶體位址,例如直接用” ”指派給一個字元串類型變量的話,如果下一個賦的也是同一個值,那麼它們指向的就是同一個記憶體位址。但是如果使用new關鍵字來建構對象指派的話,就是各自指向的自己建立的記憶體位址,這時候用==就無法比較它們的實際内容了,需要使用equals方法來進行比較。用==比較new出來的對象就會出現false的結果:
<a href="https://s4.51cto.com/wyfs02/M00/08/D3/wKiom1nnjRLTdR-uAA0Ryf9LdtM505.png" target="_blank"></a>
用equals方法則比較的是實際内容,比較new出來的對象隻要是内容一緻結果就是true:
<a href="https://s5.51cto.com/wyfs02/M02/A7/83/wKioL1nnimXx8FsGAA8VAyfJWdk839.png" target="_blank"></a>
本文轉自 ZeroOne01 51CTO部落格,原文連結:http://blog.51cto.com/zero01/1974049,如需轉載請自行聯系原作者