Java static關鍵字(靜態變量和靜態方法)

在類中,使用 static 修飾符修飾的屬性(成員變量)稱爲靜態變量,也可以稱爲類變量,常量稱爲靜態常量,方法稱爲靜態方法或類方法,它們統稱爲靜態成員,歸整個類所有。

靜態成員不依賴於類的特定實例,被類的所有實例共享,就是說 static 修飾的方法或者變量不需要依賴於對象來進行訪問,只要這個類被加載,Java 虛擬機就可以根據類名找到它們。

調用靜態成員的語法形式如下:

類名.靜態成員

注意:

  • static 修飾的成員變量和方法,從屬於類。
  • 普通變量和方法從屬於對象。
  • 靜態方法不能調用非靜態成員,編譯會報錯。

靜態變量

類的成員變量可以分爲以下兩種:

  1. 靜態變量(或稱爲類變量),指被 static 修飾的成員變量。
  2. 實例變量,指沒有被 static 修飾的成員變量。


靜態變量與實例變量的區別如下:

1)靜態變量

  • 運行時,Java 虛擬機只爲靜態變量分配一次內存,在加載類的過程中完成靜態變量的內存分配。
  • 在類的內部,可以在任何方法內直接訪問靜態變量。
  • 在其他類中,可以通過類名訪問該類中的靜態變量。


2)實例變量

  • 每創建一個實例,Java 虛擬機就會爲實例變量分配一次內存。
  • 在類的內部,可以在非靜態方法中直接訪問實例變量。
  • 在本類的靜態方法或其他類中則需要通過類的實例對象進行訪問。


靜態變量在類中的作用如下:

  • 靜態變量可以被類的所有實例共享,因此靜態變量可以作爲實例之間的共享數據,增加實例之間的交互性。
  • 如果類的所有實例都包含一個相同的常量屬性,則可以把這個屬性定義爲靜態常量類型,從而節省內存空間。例如,在類中定義一個靜態常量 PI。

 
  1. public static double PI = 3.14159256;

例 1

創建一個帶靜態變量的類,然後在 main() 方法中訪問該變量並輸出結果。


 
  1. public class StaticVar {
  2. public static String str1 = "Hello";
  3. public static void main(String[] args) {
  4. String str2 = "World!";
  5. // 直接訪問str1
  6. String accessVar1 = str1+str2;
  7. System.out.println("第 1 次訪問靜態變量,結果爲:"+accessVar1);
  8. // 通過類名訪問str1
  9. String accessVar2 = StaticVar.str1+str2;
  10. System.out.println("第 2 次訪問靜態變量,結果爲:"+accessVar2);
  11. // 通過對象svt1訪問str1
  12. StaticVar svt1 = new StaticVar();
  13. svt1.str1 = svt1.str1+str2;
  14. String accessVar3 = svt1.str1;
  15. System.out.println("第3次訪向靜態變量,結果爲:"+accessVar3);
  16. // 通過對象svt2訪問str1
  17. StaticVar svt2 = new StaticVar();
  18. String accessVar4 = svt2.str1+str2;
  19. System.out.println("第 4 次訪問靜態變量,結果爲:"+accessVar4);
  20. }
  21. }

運行該程序後的結果如下所示。

第 1 次訪問靜態變量,結果爲:HelloWorld!
第 2 次訪問靜態變量,結果爲:HelloWorld!
第 3 次訪向靜態變量,結果爲:HelloWorld!
第 4 次訪問靜態變量,結果爲:HelloWorld!World!

從運行結果可以看出,在類中定義靜態的屬性(成員變量),在 main() 方法中可以直接訪問,也可以通過類名訪問,還可以通過類的實例對象來訪問。

注意:靜態變量是被多個實例所共享的。

靜態方法

與成員變量類似,成員方法也可以分爲以下兩種:

  1. 靜態方法(或稱爲類方法),指被 static 修飾的成員方法。
  2. 實例方法,指沒有被 static 修飾的成員方法。


靜態方法與實例方法的區別如下:

  • 靜態方法不需要通過它所屬的類的任何實例就可以被調用,因此在靜態方法中不能使用 this 關鍵字,也不能直接訪問所屬類的實例變量和實例方法,但是可以直接訪問所屬類的靜態變量和靜態方法。另外,和 this 關鍵字一樣,super 關鍵字也與類的特定實例相關,所以在靜態方法中也不能使用 super 關鍵字。
  • 在實例方法中可以直接訪問所屬類的靜態變量、靜態方法、實例變量和實例方法。

例 2

創建一個帶靜態變量的類,添加幾個靜態方法對靜態變量的值進行修改,然後在 main( ) 方法中調用靜態方法並輸出結果。


 
  1. public class StaticMethod {
  2. public static int count = 1; // 定義靜態變量count
  3. public int method1() {
  4. // 實例方法method1
  5. count++; // 訪問靜態變量count並賦值
  6. System.out.println("在靜態方法 method1()中的 count="+count); // 打印count
  7. return count;
  8. }
  9. public static int method2() {
  10. // 靜態方法method2
  11. count += count; // 訪問靜態變量count並賦值
  12. System.out.println("在靜態方法 method2()中的 count="+count); // 打印count
  13. return count;
  14. }
  15. public static void PrintCount() {
  16. // 靜態方法PrintCount
  17. count += 2;
  18. System.out.println("在靜態方法 PrintCount()中的 count="+count); // 打印count
  19. }
  20. public static void main(String[] args) {
  21. StaticMethod sft = new StaticMethod();
  22. // 通過實例對象調用實例方法
  23. System.out.println("method1() 方法返回值 intro1="+sft.method1());
  24. // 直接調用靜態方法
  25. System.out.println("method2() 方法返回值 intro1="+method2());
  26. // 通過類名調用靜態方法,打印 count
  27. StaticMethod.PrintCount();
  28. }
  29. }

運行該程序後的結果如下所示。

在靜態方法 method1()中的 count=2
method1() 方法返回值 intro1=2
在靜態方法 method2()中的 count=4
method2() 方法返回值 intro1=4
在靜態方法 PrintCount()中的 count=6

在該程序中,靜態變量 count 作爲實例之間的共享數據,因此在不同的方法中調用 count,值是不一樣的。從該程序中可以看出,在靜態方法 method1() 和 PrintCount() 中是不可以調用非靜態方法 method1() 的,而在 method1() 方法中可以調用靜態方法 method2() 和 PrintCount()。

在訪問非靜態方法時,需要通過實例對象來訪問,而在訪問靜態方法時,可以直接訪問,也可以通過類名來訪問,還可以通過實例化對象來訪問。

靜態代碼塊

靜態代碼塊指 Java 類中的 static{ } 代碼塊,主要用於初始化類,爲類的靜態變量賦初始值,提升程序性能。

靜態代碼塊的特點如下:

  • 靜態代碼塊類似於一個方法,但它不可以存在於任何方法體中。
  • 靜態代碼塊可以置於類中的任何地方,類中可以有多個靜態初始化塊。 
  • Java 虛擬機在加載類時執行靜態代碼塊,所以很多時候會將一些只需要進行一次的初始化操作都放在 static 代碼塊中進行。
  • 如果類中包含多個靜態代碼塊,則 Java 虛擬機將按它們在類中出現的順序依次執行它們,每個靜態代碼塊只會被執行一次。
  • 靜態代碼塊與靜態方法一樣,不能直接訪問類的實例變量和實例方法,而需要通過類的實例對象來訪問。

例 3

編寫一個 Java 類,在類中定義一個靜態變量,然後使用靜態代碼塊修改靜態變量的值。最後在 main() 方法中進行測試和輸出。


 
  1. public class StaticCode {
  2. public static int count = 0;
  3. {
  4. count++;
  5. System.out.println("非靜態代碼塊 count=" + count);
  6. }
  7. static {
  8. count++;
  9. System.out.println("靜態代碼塊1 count=" + count);
  10. }
  11. static {
  12. count++;
  13. System.out.println("靜態代碼塊2 count=" + count);
  14. }
  15.  
  16. public static void main(String[] args) {
  17. System.out.println("*************** StaticCode1 執行 ***************");
  18. StaticCode sct1 = new StaticCode();
  19. System.out.println("*************** StaticCode2 執行 ***************");
  20. StaticCode sct2 = new StaticCode();
  21. }
  22. }

如上述示例,爲了說明靜態代碼塊只被執行一次,特地添加了非靜態代碼塊作爲對比,並在主方法中創建了兩個類的實例對象。上述示例的執行結果爲:

靜態代碼塊1 count=1
靜態代碼塊2 count=2
*************** StaticCode1 執行 ***************
非靜態代碼塊 count=3
*************** StaticCode2 執行 ***************
非靜態代碼塊 count=4

上述代碼中 { } 代碼塊爲非靜態代碼塊,非靜態代碼塊是在創建對象時自動執行的代碼,不創建對象不執行該類的非靜態代碼塊。代碼域中定義的變量都是局部的,只有域中的代碼可以調用。 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章