您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關static關鍵字作用是什么,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。
static關鍵字的含義及使用場景
static是Java50個關鍵字之一。static關鍵字可以用來修飾代碼塊表示靜態代碼塊,修飾成員變量表示全局靜態成員變量,修飾方法表示靜態方法。(注意:不能修飾普通類,除了內部類,這是為什么?)
class A { static { System.out.println("A : 靜態代碼塊"); } static int i ; // 靜態變量 static void method() { System.out.println("A: 靜態方法"); } }
簡而言之,被static關鍵字修飾的內容都是靜態的。
靜態是相對于動態的,動態是指Java程序在JVM上運行時,JVM會根據程序的需要動態創建對象并存儲對象(分配內存),對象使命結束后,對象會被垃圾回收器銷毀,即內存回收由JVM統一管理并分配給其他新創建的對象;靜態是指Java程序還沒有運行時,JVM就會為加載的類分配空間存儲被static關鍵字修飾的內容;如靜態成員變量,Java類加載到JVM中,JVM會把類以及類的靜態成員變量存儲在方法區,我們知道方法區是線程共享且很少發生GC的區域,所以被static關鍵字修飾的內容都是全局共享的,且只會為其分配一次存儲空間。
所以當類的某些內容不屬于對象,而由對象共享即屬于類的時候,就可以考慮是否用static關鍵字進行修飾。
static關鍵字的的作用
1 修飾代碼塊
類中用static關鍵字修飾的代碼塊稱為靜態代碼,反之沒有用static關鍵字修飾的代碼塊稱為實例代碼塊。
實例代碼塊會隨著對象的創建而執行,即每個對象都會有自己的實例代碼塊,表現出來就是實例代碼塊的運行結果會影響當前對象的內容,并隨著對象的銷毀而消失(內存回收);而靜態代碼塊是當Java類加載到JVM內存中而執行的代碼塊,由于類的加載在JVM運行期間只會發生一次,所以靜態代碼塊也只會執行一次。
因為靜態代碼塊的主要作用是用來進行一些復雜的初始化工作,所以靜態代碼塊跟隨類存儲在方法區的表現形式是靜態代碼塊執行的結果存儲在方法區,即初始化量存儲在方法區并被線程共享。
2 修飾成員變量
類中用static關鍵字修飾的成員變量稱為靜態成員變量,因為static不能修飾局部變量(為什么?),因此靜態成員變量也能稱為靜態變量。靜態變量跟代碼塊類似,在類加載到JVM內存中,JVM會把靜態變量放入方法區并分配內存,也由線程共享。訪問形式是:類名.靜態成員名。
public class StaticTest { public static void main(String[] args) { System.out.println(D.i); System.out.println(new D().i); } } class D { static { i = 2; System.out.println("D : 靜態代碼塊1"); } static int i; }
靜態變量存儲在類的信息中,且可以在線程間共享,那么它當然也屬于該類的每個對象,因此可以通過對象訪問靜態變量,但編譯器并不支持這么做,且會給出警告。
注意:
一個類的靜態變量和該類的靜態代碼塊的加載順序。類會優先加載靜態變量,然后加載靜態代碼塊,但有多個靜態變量和多個代碼塊時,會按照編寫的順序進行加載。
class D { static { i = 2; System.out.println("D : 靜態代碼塊1"); } static { i = 6; System.out.println("D : 靜態代碼塊2"); } static int i; }
可以想一下運行的結果。
靜態變量可以不用顯式的初始化,JVM會默認給其相應的默認值。如基本數據類型的byte為0,short為0,char為\u0000,int為0,long為0L,float為0.0f,double為0.0d,boolean為false,引用類型統一為null。
靜態變量既然是JVM內存中共享的且可以改變,那么對它的訪問會引起線程安全問題(線程A改寫的同時,線程B獲取它的值,那么獲取的是修改前的值還是修改后的值呢?),所以使用靜態變量的同時要考慮多線程情況。如果能確保靜態變量不可變,那么可以用final關鍵字一起使用避免線程安全問題;否則需要采用同步的方式避免線程安全問題,如與volatile關鍵字一起使用等。
static關鍵不能修飾局部變量,包括實例方法和靜態方法,不然就會與static關鍵字的初衷-共享相違背。
3 修飾方法
用static關鍵字修飾的方法稱為靜態方法,否則稱為實例方法。通過類名.方法名調用,但需要注意靜態方法可以直接調用類的靜態變量和其他靜態方法,不能直接調用成員變量和實例方法(除非通過對象調用)。
class D { static { i = 2; System.out.println("D : 靜態代碼塊"); } static final int i; int j; static void method() { System.out.println(i); System.out.println(new D().j); method1(); new D().method2(); } static void method1() { System.out.println(i); } void method2() { System.out.println(i); } }
注意:既然類的實例方法需要對象調用才能訪問,而靜態方法直接通過類名就能訪問,那么在不考慮部署服務器的情況下,一個類是如何開始執行的呢?最大的可能就是通過“類名.靜態方法”啟動Java,而我定義那么多靜態方法,JVM又是如何知道主入口呢?
或許,你想到了main方法。
沒錯,就是main方法被Java規范定義成Java類的主入口。Java類的運行都由main方法開啟:
public static void main(String[] args) { for (String arg : args) { // 參數由外部定義 System.out.println(arg); }}
但注意main并不是Java關鍵字,它只是一個規定的程序入口的方法名字;另外main方法可以重載。
注意:static關鍵字雖然不能修飾普通類,但可以用static關鍵字修飾內部類使其變成靜態內部類。static關鍵字本身的含義就是共享,而Java類加載到JVM內存的方法區,也是線程共享的,所以沒必要用static關鍵字修飾普通類。
4 靜態導入
在用import導入包或者類時,可以用static修飾包名或者類,表示靜態導入。靜態導入可以與動態導入放在一起比較來加深理解。
動態導入是當你程序運行時需要new一個不在此包中的類的對象時,才會根據全路徑類名加載類;而靜態導入則是隨著類的加載而加載靜態導入的類,所以它是提前導入的。
public class StaticTest { static void method1() { System.out.println("static method1"); } static void method2() { System.out.println("static method2"); } }
靜態導入:
import static com.starry.staticImport.StaticTest.method1; public class Client { public static void main(String[] args) { method1(); // StaticTest.method2(); } }
注意method1()是靜態導入,所以可以不需要通過類名訪問;而method2()沒有導入,則需要通過類名調用。那么什么時候需要靜態導入呢?
靜態導入常用于靜態方法以及含有靜態方法的類,枚舉類等的導入,可以在編譯階段確定導入類的信息或者方法信息。
static關鍵字的缺點
封裝是Java類的三大特性之一,也是面向對象的主要特性。因為不需要通過對象,而直接通過類就能訪問類的屬性和方法,這有點破壞類的封裝性;所以除了Utils類,代碼中應該盡量少用static關鍵字修飾變量和方法
關于static關鍵字作用是什么就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。