Java修飾符 --- static
@
目錄一、靜態變數和靜態方法
- 被 static 修飾的變數為類變數,也就是靜態變數,可以直接通過
類名.變數名
引用,也可以通過 new 例項物件呼叫 - 被 static 修飾的方法為類方法,也就是靜態方法,可以直接通過
類名.方法名
引用,也可以通過 new 例項物件呼叫 - 靜態變數和靜態方法統一屬於類的靜態資源,是類例項之間共享的,也就是
一處變,到處變
,是同步的,生命週期長,隨類的建立而生,隨類的結束而結束
二、靜態變數和非靜態變數的區別?
-
靜態變數是屬於類的,當且僅當在類初始化的時候載入,在記憶體只有一個副本,被所有物件(類例項)共享
-
非靜態變數是物件的,每次建立物件的時候初始化,存在多個副本,各個物件擁有的副本互不影響
-
靜態變數是存放在方法區的,而非靜態變數在堆區
方法區:存放已經載入的類資訊、常量、靜態變數以及方法程式碼的記憶體區域
常量池:是方法區的一部分,主要用來存放常量和類中的符號引用等資訊
堆區:用於存放類的物件例項
棧區:也叫 Java 虛擬棧,由一個一個的棧幀組成的先進後出的棧式結構,棧幀中存放方法執行時產生的區域性變數、方法出口等資訊,當呼叫一個方法時,虛擬機器棧會建立一個棧幀存放這些資料,當方法完成時,棧幀消失,如果方法中呼叫了其他方法,則繼續在棧頂
建立新的棧幀
三、關於靜態方法能否引用非靜態資源等問題?
-
例子:
public class staticTest { private int number = 333; public static void main(String[] args) { number = 1; } }
這段程式碼編譯都不會通過,執行的話會報錯:無法從靜態上下文中引用非靜態變數
原因:
靜態資源屬於類,但是是獨立於類存在的,存在方法區(靜態區),JVM的類載入機制中,靜態資源是在類初始化的時候載入,而非靜態資源是在類
new
建立的時候載入,也就是說靜態資源的初始化早於非靜態資源。所有上述程式碼中,先執行 main 方法的時候,成員變數 number 還沒初始化。總結:
靜態方法只能引用靜態資源,非靜態方法可以引用靜態資源和非靜態資源
四、靜態程式碼塊
用於初始化一個類的時候做操作用的,靜態塊裡的程式碼只在初始化的時候執行一次
執行順序(雙親委託載入):
-
一個類:類內容(靜態變數、靜態初始化塊)=> 例項內容(變數、初始化塊、構造器)
-
繼承關係類:父類(靜態變數、靜態初始化塊)=> 子類(靜態變數、靜態初始化塊)=> 父類(變數、初始化塊、構造器)=> 子類(變數、初始化塊、構造器)
-
例子:
public class staticTest { static { number = 333; System.out.println(number); } private static int number; }
注意:上面程式碼列印會報錯:不能定義之前引用,也就是說:
靜態程式碼塊對應定義在它之後的靜態變數,可以賦值,但是不能訪問
五、靜態內部類
-
靜態內部類作用:
1.內部類一般只為其外部類使用
2.內部類存在外部類的引用,可以直接訪問外部類屬性
每個內部類都能單獨繼承一個介面,而無論外部類是否已經繼承該介面(內部類使多重繼承的解決方案更加完美)
-
外部類以物件的方式(建立物件訪問)使用內部類,可以訪問內部類所有的方法和屬性,包括私有方法和屬性
內部類不能訪問外部類所在的區域性變數,只能訪問 final 修飾的區域性變數
在方法內定義內部類時,如果內部類呼叫了方法中的變數,那麼該變數必須申明為final型別,為什麼?後來想到應該是生命週期的原因,因為方法內定義的變數是區域性變數,離開該方法,變數就失去了作用,也就會自動被消除,而內部類卻不會離開它所在方法就失去作用