1. 引言
在本文中窟蓝,我們將詳細探討Java語言的static關(guān)鍵字。我們將找到如何將關(guān)鍵字static應(yīng)用于變量篮绿,方法孵延,塊,嵌套類及其區(qū)別亲配。
2.靜態(tài)關(guān)鍵字剖析
在Java編程語言中尘应,關(guān)鍵字static指示特定成員屬于某個類型本身,而不是該類型的實例吼虎。
這意味著僅創(chuàng)建該靜態(tài)成員的一個實例犬钢,該實例在該類的所有實例之間共享。
關(guān)鍵字可以應(yīng)用于變量思灰,方法玷犹,塊和嵌套類。
3. 靜態(tài)字段(或類變量)
在Java中洒疚,如果將某個字段聲明為靜態(tài)歹颓,則將創(chuàng)建該字段的單個副本并在該類的所有實例之間共享。我們初始化一個類多少次并不重要油湖。永遠只有一個靜態(tài)字段的副本屬于它巍扛。此靜態(tài)字段的值將在任何不同類的相同對象之間共享。
從內(nèi)存的角度來看乏德,靜態(tài)變量進入JVM內(nèi)存中稱為Metaspace的特定池(在Java 8之前撤奸,此池稱為Permanent Generation或PermGen,現(xiàn)已完全刪除并替換為Metaspace)喊括。
3.1 靜態(tài)字段示例
假設(shè)我們有一個帶有幾個屬性(實例變量)的Car類寂呛。每當從此Car藍圖初始化新對象時,每個新對象都會擁有這些實例變量的不同副本瘾晃。
但是,假設(shè)我們正在尋找一個變量幻妓,該變量保存已初始化并在所有實例之間共享的Car對象的數(shù)量蹦误,以便它們可以訪問它并在初始化時對其進行遞增。
這就是靜態(tài)變量的來源:
現(xiàn)在肉津,對于初始化的此類的每個對象强胰,numberOfCars變量的相同副本將遞增。因此妹沙,對于這種情況偶洋,以下斷言將成立:
3.2 使用靜態(tài)字段的令人信服的理由
當變量的值獨立于對象時
該值應(yīng)該在所有對象之間共享時
3.3 要記住的要點
由于靜態(tài)變量屬于一個類,因此可以使用類名稱直接訪問它們距糖,并且不需要任何對象引用
靜態(tài)變量只能在類級別聲明
無需對象初始化即可訪問靜態(tài)字段
盡管我們可以使用對象引用(例如ford.numberOfCars ++)訪問靜態(tài)字段玄窝,但我們應(yīng)避免使用它牵寺,因為在這種情況下,很難確定它是實例變量還是類變量恩脂;相反帽氓,我們應(yīng)該始終使用類名來引用靜態(tài)變量(例如,在本例中為Car.numberOfCars ++)
4.靜態(tài)方法(或類方法)
與靜態(tài)字段類似俩块,靜態(tài)方法也屬于類而不是對象黎休,因此可以在不創(chuàng)建其所在類的對象的情況下調(diào)用它們。它們應(yīng)在不創(chuàng)建類對象的情況下使用玉凯。
4.1 靜態(tài)方法示例
靜態(tài)方法通常用于執(zhí)行不依賴于實例創(chuàng)建的操作势腮。
如果應(yīng)該在該類的所有實例之間共享一個代碼,請使用靜態(tài)方法編寫該代碼:
靜態(tài)方法還廣泛用于創(chuàng)建實用程序或幫助程序類漫仆,因此無需創(chuàng)建這些類的新對象即可獲取它們捎拯。
只需查看JDK的Collections或Math實用程序類,Apache的StringUtils或Spring框架的CollectionUtils歹啼,然后注意所有方法都是靜態(tài)的玄渗。
4.2 使用靜態(tài)方法的令人信服的理由
訪問/操作靜態(tài)變量和其他不依賴對象的靜態(tài)方法
靜態(tài)方法廣泛用于實用程序和幫助程序類
4.3 要記住的要點
·Java中的靜態(tài)方法在編譯時解析。由于方法覆蓋是運行時多態(tài)性的一部分狸眼,因此靜態(tài)方法不能被覆蓋
·抽象方法不能是靜態(tài)的
·靜態(tài)方法不能使用此關(guān)鍵字或超級關(guān)鍵字
· 實例藤树,類方法和變量的以下組合是有效的:
? ? ? 1. 實例方法可以直接訪問實例方法和實例變量
? ? ? 2. 實例方法還可以直接訪問靜態(tài)變量和靜態(tài)方法
? ? ? 3. 靜態(tài)方法可以訪問所有靜態(tài)變量和其他靜態(tài)方法
? ? ? 4. 靜態(tài)方法不能直接訪問實例變量和實例方法;他們需要一些對象引用來這樣做
5.靜態(tài)塊
靜態(tài)塊用于初始化靜態(tài)變量拓萌。盡管可以在聲明期間直接初始化靜態(tài)變量岁钓,但是在某些情況下,我們需要進行多行處理微王。
在這種情況下屡限,靜態(tài)塊會派上用場。
如果靜態(tài)變量在初始化時需要其他多語句邏輯炕倘,則可以使用靜態(tài)塊钧大。
5.1 靜態(tài)塊示例
假設(shè)我們要使用一些預(yù)定義的值來初始化列表對象。
使用靜態(tài)塊罩旋,這變得容易:
在這個例子中啊央,不可能用所有初始值和聲明來初始化List對象。這就是為什么我們在這里利用靜態(tài)塊的原因涨醋。
5.2 使用靜態(tài)塊的令人信服的理由
如果靜態(tài)變量的初始化需要除分配外的一些其他邏輯
如果靜態(tài)變量的初始化容易出錯并且需要異常處理
5.3 要記住的要點
一個類可以有多個靜態(tài)塊
靜態(tài)字段和靜態(tài)塊的解析和執(zhí)行順序與類中存在的順序相同
6. 靜態(tài)類
Java編程語言允許我們在一個類中創(chuàng)建一個類瓜饥。它提供了一種令人信服的方式,可以將只在一個地方使用的元素進行分組浴骂,這有助于使我們的代碼更加井井有條乓土,可讀性強。
嵌套類的體系結(jié)構(gòu)分為兩種:
聲明為靜態(tài)的嵌套類稱為靜態(tài)嵌套類,而非靜態(tài)的嵌套類稱為內(nèi)部類
兩者之間的主要區(qū)別在于內(nèi)部類可以訪問封閉類的所有成員(包括私有類)趣苏,而靜態(tài)嵌套類僅可以訪問外部類的靜態(tài)成員狡相。
實際上,靜態(tài)嵌套類的行為與任何其他頂級類完全相同拦键,但包含在將對其進行訪問的唯一類中谣光,以提供更好的打包便利。
6.1 靜態(tài)類的例子
6.2 使用靜態(tài)內(nèi)部類的令人信服的理由
將僅在一個地方使用的類分組會增加封裝
代碼被帶到了更接近使用它的地方芬为。這提高了可讀性萄金,代碼更易于維護
如果嵌套類不需要對其封閉的類實例成員的任何訪問,則最好將其聲明為靜態(tài)媚朦,因為這樣一來氧敢,它就不會與外部類耦合,因此將是最優(yōu)的询张,因為它們不需要任何堆或堆棧內(nèi)存
6.3 要記住的要點
靜態(tài)嵌套類無權(quán)訪問封閉的外部類的任何實例成員孙乖;它只能通過對象的引用訪問它們
靜態(tài)嵌套類可以訪問封閉類的所有靜態(tài)成員,包括私有成員
Java編程規(guī)范不允許我們將頂級類聲明為靜態(tài)類份氧。只能將這些類(嵌套類)中的類設(shè)為靜態(tài)唯袄。
7.結(jié)論
在本文中,我們看到了static關(guān)鍵字的作用蜗帜。我們還了解了使用靜態(tài)字段恋拷,靜態(tài)方法,靜態(tài)塊和靜態(tài)內(nèi)部類的原因和優(yōu)勢厅缺。