static 用法 1.static 變數 static變數又稱為靜態變數,靜態變數保存在方法區靜態域中,一個類的靜態變數被其所有實例共用。 2.static方法 靜態方法不與包含它的任何對象關聯,即使沒有創建對象,也可使用,例: 1 public class StaticTest { 2 3 pu ...
static 用法
1.static 變數
static變數又稱為靜態變數,靜態變數保存在方法區靜態域中,一個類的靜態變數被其所有實例共用。
2.static方法
靜態方法不與包含它的任何對象關聯,即使沒有創建對象,也可使用,例:
1 public class StaticTest { 2 3 public static void sayHello(){ 4 System.err.println("Hello"); 5 } 6 7 } 8 9 class Greeting{ 10 11 public static void main(String[] args) { 12 StaticTest.sayHello(); 13 } 14 }View Code
3.static代碼塊
static代碼塊在類初次被引用或者實例化時執行且只執行一次,一個類里可以有多個static代碼塊,會按照順序執行,例:
1 public class StaticTest { 2 3 static { 4 System.err.println("Wave hands"); 5 } 6 7 public static void sayHello(){ 8 System.err.println("say Hello"); 9 } 10 11 } 12 13 class Greeting{ 14 15 public static void main(String[] args) { 16 StaticTest.sayHello(); 17 } 18 }View Code
4.static類
普通類是不能被static修飾的,static只能修飾內部類;這種內部類通常稱為 嵌套類
“如果不需要內部類對象與其外圍類對象之間有聯繫,那麼可以將內部類聲明為static”(《java編程思想p201》);
普通的內部類對象都會隱式的保存一個引用指向創建他的外部類,然而關於嵌套類:
1)要創建嵌套類的對象,並不需要其外圍類的對象。
2)不能從嵌套類的對象中訪問非靜態的外圍類對象。
例如jdk中ThreadLocal類就有較多的應用;
/**關於內部類部分後續討論*/
擴展內容
類從載入到虛擬機記憶體中開始,到卸載記憶體位置,它的真個聲明周期包括:載入、驗證、準備、解析、初始化、使用、卸載;
有且僅有以下四種情況下,類必須進行初始化:
1)遇到new(使用new關鍵字實例化對象)
getstatic、putstatic(讀取或設置一個類的靜態欄位(被final修飾、已在編譯期把結果放入常量池的靜態欄位除外))
invokestatic(調用一個類的靜態方法的時候)
2)使用java.lang.reflect包的方法對類進行反射調用的時候
3)初始化一個類時,發現其父類沒有進行過初始化的時候
4)當虛擬機啟動時,用戶需要指定一個要執行的主類,虛擬機會初始化這個主類;
對於靜態欄位,只有直接引用定義這個欄位的類才會觸發該類的初始化,而通過子類引用父類的欄位,只會觸發父類的初始化,而不會觸發子類的初始化,例:
1 package com.neal.tutorial.basic.keyword; 2 3 public class StaticTest { 4 5 static int a = 5; 6 7 static { 8 System.err.println("a in parent: " + a); 9 } 10 11 } 12 13 class SubStatic extends StaticTest { 14 15 static int b = 10; 16 17 static{ 18 System.err.println(b); 19 } 20 21 } 22 23 class Greeting { 24 25 public static void main(String[] args) { 26 System.err.println(SubStatic.a); 27 } 28 }View Code
輸出結果為
1 a in parent: 5 2 5View Code
可以看出子類中靜態代碼塊並沒有執行;
final關鍵字用法
1.變數
1)基本類型:
當我們需要一個編譯時不改變常量,或者一個運行時被初始化後就不改變的值時,通常定義一個final修飾的基本類型變數
當與static一起使用時,意為一個只有一份的常量(即多個實例共用)
2)對象:
當變數類型為對象時,final變數的引用在初始化後不可更改,但是引用指向的對象值是可變的,例如數組、Map、List等
3)參數列表
當在參數列表中聲明參數為final時,意味著在方法中只能讀取參數引用的對象,而無法修改參數引用指向的對象,這一特性主要用於向匿名內部類傳遞參數
2.final方法
final方法一般用於兩種情景下
1)想要鎖定方法,防止任何繼承類修改它的含義,確保在繼承中使方法行為保持不變,並且不會被覆蓋
2)出於性能考慮,在java早期實現中(現在不鼓勵這麼做)如果一個方法被指明為final,就是允許編譯器將針對該方法的所有調用都轉為內嵌調用
內嵌機制是指final方法會在編譯時進行inline優化,即在編譯時直接調用方法代碼替換,而不是在運行時。而非final方法可能存在被子類重寫,由於多態的原因,並不能在編譯時就確定調用的是哪個方法
3.final類
final類不能夠被繼承,一般在確定該類不需要子類時,將類定義為final類型
在jdk源碼中,String類就被定義為final類型
參考:
https://www.zhihu.com/question/64763016/answer/223938175
《java編程思想》第四版
ps.小王知識點 :當你舉起屠刀的那一刻,就將知道自己必將死於刀下