通過案例瞭解靜態修飾符static使用場景
今天在csdn上看到一個關於static的帖子,裡面的某個人的回覆引起了我的注意。回覆的大概意思是說:"面向物件裡面的靜態修飾是面向物件程式設計帶來的垃圾產物,應儘量避免使用。"這句話大體能夠體現static在大部分軟體工程師眼裡的尷尬地位,有一部分軟體工程師除了在剛開始學習的時候,有使用過static外,就再也沒有接觸過static了。對此,我不得不說,這是一種遺憾。static是面向物件這個大家庭裡面不可或缺的一員,少了它,面向物件的程式設計將少了許多的樂趣,多了許多煩擾。
一、什麼是static修飾符
許多書和人都喜歡把static稱之為靜態,但我不喜歡這樣稱呼它,我更喜歡直接叫它static。因為我認為靜態這兩個字無法真正表達出static的真正作用。在程式中任何變數或者成員都是在編譯時由系統自動分配記憶體來儲存的,而用static修飾的成員會儲存在一個static記憶體區中並且一直存在,直到程式退出記憶體才會釋放這個空間,也就是隻要程式在執行,那麼這塊記憶體就會一直存在。那麼這樣的設計有什麼意義了?在面向物件的概念中,這樣的設計可是十分有意義的!因為這樣的設計,static可以用來區分成員變數、方法是屬於類本身還是屬於類例項化後的物件。有static修飾的成員屬於類本身,沒有static修飾的成員屬於類的例項。
可能很多人還是不能理解,我在這邊快速簡單的寫個例子吧。
class a{ public $aa = 1; public function aa(){ $this->aa += 1; echo $this->aa; } } class b{ public function bb(){ $aaa = new a(); $aaa->aa(); } } class c{ public function cc(){ $aaa = new a(); $aaa->aa(); } } $bbb = new b(); $ccc = new c(); $bbb->bb(); echo '*******************'; $ccc->cc();
注:在"this->aa"裡面的"->"是php呼叫方法的方式類似於java裡面的"."
上面程式碼很簡單相信大家都能理解,我就不解釋了。執行後的結果是2*******************2。
上面的程式碼是沒用static的情況,下面我就再寫一個用了static的demo。
class a{ public static $aa = 1; public static function aa(){ self::$aa += 1; echo self::$aa; } } class b{ public function bb(){ a::aa(); } } class c{ public function cc(){ a::aa(); } } $bbb = new b(); $ccc = new c(); $bbb->bb(); echo '*******************'; $ccc->cc();
注:"self::"和"::"是php中呼叫static修飾的成員的方式。裡面的差異與本文要探討的內容關係不大,咱不解釋,有興趣的可以自行研究。
最後的執行結果是2*******************3。這說明了,在static修飾下的成員變數$aa在第一次呼叫後並沒有被釋放,而是依然存在static記憶體塊中,所有在第二次呼叫後輸出的結果是3。因為第一次呼叫後的變數$aa從1變成了2,第二次呼叫的時候$aa還是2,所有二次呼叫後$aa變成了3。這就是static修飾的變數會一直存在的體現。同時,要記住在面向物件的程式設計中static修飾的成員不能直接呼叫非static修飾的成員。如果你知道了static的原理這個就很好理解了。拿java舉例,用static修飾的成員,是專門儲存在一個static記憶體區裡面。非static修飾的成員是儲存在堆記憶體裡面。兩者是分開儲存的,所以要想在static修飾的成員裡面呼叫非static修飾的成員,就必須跟在外面呼叫一樣,先例項化,在呼叫。對於那為什麼可以在非static修飾的成員裡面直接呼叫static修飾的成員這個問題,我的解釋是,你在類外面呼叫static成員時不也是可以不例項化類就直接呼叫嗎?更何況在類裡面了?
雖然可以在非static修飾的成員裡面直接呼叫static修飾的成員,但是我強烈建議大家不要這麼做!原因後面會提到。
二、什麼時候使用static修飾符
理解了上面說的,你只是初步瞭解了static,要想更近一步的理解static,就要讀懂這句話:"static可以用來區分成員變數、方法是屬於類本身還是屬於類例項化後的物件。有static修飾的成員屬於類本身,沒有static修飾的成員屬於類的例項。"很多初學者會搞不懂類和類的例項有什麼不同?類是抽象的存在,而類的例項是類具體化的存在。兩者是有區別的,因此就會發生一種情況,那就是有些類例項化後沒有任何意義,也就是說沒有例項化的必要,只有作為類才有意義。這時候,就必須用static來修飾成員變數和方法,表明這些變數和方法只屬於類本身。比如:在做一個專案的時候,一個合格的軟體工程師都會封裝一個公共方法類,將經常用的公共方法放在裡面,以便隨時在專案中呼叫。這時候,你會發現,這個公共方法類,並沒有一個合適的具體化的例項可以來表示,只有作為類的時候,才有其意義。所以裡面的公共方法都可以用static來修飾,以表示這些方法都屬於類本身,就不需要每一次使用一個公共方法的時候都要例項化出一個具體的物件了。還有就是像做安全防範(sql注入過濾、xss過濾等)的時候,將其統一封裝成一個Security類,裡面的方法就需要用到static來修飾,不然難道每一次過濾都要例項化一次嗎?再開一個堆記憶體空間?類似的還有語言包、快取等等。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。