java中static的理解(轉載)
阿新 • • 發佈:2018-12-18
使用 static 修飾符修飾的屬性(成員變數)、常量和成員方法稱為靜態變數、常量和方法,它們統稱為
靜態成員,歸整個類所有,不依賴於類的特定例項,被類的所有例項共享。只要這個類被載入,
Java 虛擬機器就可以根據類名在執行時資料區的方法區內找到它們。
呼叫靜態成員的語法形式如下:
靜態變數與例項變數的區別如下:
靜態變數在類中的作用如下:
執行該程式後的結果如下所示。
從執行結果可以看出, 在類中定義靜態的屬性(成員變數),在 main() 方法中可以直接訪問,也可以通過類名訪問,還可以通過類的例項物件來訪問。
注意:靜態變數是被多個例項所共享的。
靜態方法與例項方法的區別如下:
執行該程式後的結果如下所示。
在該程式中,靜態變數 count 作為例項之間的共享資料,因此在不同的方法中呼叫 count,值是不一樣的。從該程式中可以看出,在靜態方法 method1() 和 PrintCount() 中是不可以呼叫非靜態方法 method1() 的,而在 method1() 方法中可以呼叫靜態方法 method2() 和 PrintCount()。
在訪問非靜態方法時,需要通過例項物件來訪問,而在訪冋靜態方法時,可以直接訪問,也可以通過類名來訪問,還可以通過例項化物件來訪問。
如上述示例,為了說明靜態程式碼塊只被執行一次,特地添加了非靜態程式碼塊作為對比,並在主方法中建立了兩個類的例項物件。上述示例的執行結果為:
呼叫靜態成員的語法形式如下:
類名.靜態成員
靜態變數
實際上類的成員變數可以分為兩種:靜態變數(或稱為類變數),指被 static 修飾的成員變數;例項變數,指沒有被 static 修飾的成員變數。靜態變數與例項變數的區別如下:
- 對於靜態變數,執行時,Java 虛擬機器只為靜態變數分配一次記憶體,在載入類的過程中完成靜態變數的記憶體分配。在類的內部,可以在任何方法內直接訪問靜態變數;在其他類中,可以通過類名訪問該類中的靜態變數。
- 對於例項變數,每建立一個例項,Java 虛擬機器就會為例項變數分配一次記憶體。在類的內部,可以在非靜態方法中直接訪問例項變數;在本類的靜態方法或其他類中則需要通過類的例項物件進行訪問。
靜態變數在類中的作用如下:
- 靜態變數可以被類的所有例項共享,因此靜態變數可以作為例項之間的共享資料,增加例項之間的互動性。
- 如果類的所有例項都包含一個相同的常量屬性,則可以把這個屬性定義為靜態常量型別,從而節省記憶體空間。例如,在類中定義一個靜態常量 PI。
複製純文字複製
- public
static double PI=3.14159256;
public static double PI=3.14159256;
例 1
建立一個帶靜態變數的類,然後在 main() 方法中訪問該變數並輸出結果。複製純文字複製
- public class StaticVar
- {
- public static String str1="Hello";
- public static void main(String[]
args)
- {
- String str2="World!";
- //直接訪問str1
- String accessVar1=str1+str2;
- System.out.println("第 1 次訪問靜態變數,結果為:"+accessVar1);
- //通過類名訪問str1
- String accessVar2=StaticVar.str1+str2;
- System.out.println("第 2 次訪問靜態變數,結果為:"+accessVar2);
- //通過物件svt1訪問str1
- StaticVar svt1=new StaticVar();
- svt1.str1=svt1.str1+str2;
- String accessVar3=svt1.str1;
- System.out.println("第3次訪向靜態變數,結果為:"+accessVar3);
- //通過物件svt2訪問str1
- StaticVar svt2=new StaticVar();
- String accessVar4=svt2.str1+str2;
- System.out.println("第 4 次訪問靜態變數,結果為:"+accessVar4);
- }
- }
public class StaticVar { public static String str1="Hello"; public static void main(String[] args) { String str2="World!"; //直接訪問str1 String accessVar1=str1+str2; System.out.println("第 1 次訪問靜態變數,結果為:"+accessVar1); //通過類名訪問str1 String accessVar2=StaticVar.str1+str2; System.out.println("第 2 次訪問靜態變數,結果為:"+accessVar2); //通過物件svt1訪問str1 StaticVar svt1=new StaticVar(); svt1.str1=svt1.str1+str2; String accessVar3=svt1.str1; System.out.println("第3次訪向靜態變數,結果為:"+accessVar3); //通過物件svt2訪問str1 StaticVar svt2=new StaticVar(); String accessVar4=svt2.str1+str2; System.out.println("第 4 次訪問靜態變數,結果為:"+accessVar4); } }
執行該程式後的結果如下所示。
第 1 次訪問靜態變數,結果為:HelloWorld! 第 2 次訪問靜態變數,結果為:HelloWorld! 第 3 次訪向靜態變數,結果為:HelloWorld! 第 4 次訪問靜態變數,結果為:HelloWorld!World!
從執行結果可以看出, 在類中定義靜態的屬性(成員變數),在 main() 方法中可以直接訪問,也可以通過類名訪問,還可以通過類的例項物件來訪問。
注意:靜態變數是被多個例項所共享的。
靜態方法
與成員變數類似,成員方法也可以分為兩種:靜態方法(或稱為類方法),指被 static 修飾的成員方法;例項方法,指沒有被 static 修飾的成員方法。靜態方法與例項方法的區別如下:
- 靜態方法不需要通過它所屬的類的任何例項就可以被呼叫,因此在靜態方法中不能使用 this 關鍵字,也不能直接訪問所屬類的例項變數和例項方法,但是可以直接訪問所屬類的靜態變數和靜態方法。另外,和 this 關鍵字一樣,super 關鍵字也與類的特定例項相關,所以在靜態方法中也不能使用 super 關鍵字。
- 在例項方法中可以直接訪問所屬類的靜態變數、靜態方法、例項變數和例項方法。
例 2
建立一個帶靜態變數的類,新增幾個靜態方法對靜態變數的值進行修改,然後在 main() 方法中呼叫靜態方法並輸出結果。複製純文字複製
- public class StaticMethod
- {
- public static int count=1; //定義靜態變數count
- public int method1()
- { //例項方法method1
- count++; //訪問靜態變數count並賦值
- System.out.println("在靜態方法 method1()中的 count="+count); //列印count
- return count;
- }
- public static int method2()
- { //靜態方法method2
- count+=count; //訪問靜態變數count並賦值
- System.out.println("在靜態方法 method2()中的 count="+count); //列印count
- return count;
- }
- public static void PrintCount()
- { //靜態方法PrintCount
- count+=2;
- System.out.println("在靜態方法 PrintCount()中的 count="+count); //列印count
- }
- public static void main(String[] args)
- {
- StaticMethod sft=new StaticMethod();
- //通過例項物件呼叫例項方法
- System.out.println("method1() 方法返回值 intro1="+sft.method1());
- //直接呼叫靜態方法
- System.out.println("method2() 方法返回值 intro1="+method2());
- //通過類名呼叫靜態方法,列印coimt
- StaticMethod.PrintCount();
- }
- }
public class StaticMethod { public static int count=1; //定義靜態變數count public int method1() { //例項方法method1 count++; //訪問靜態變數count並賦值 System.out.println("在靜態方法 method1()中的 count="+count); //列印count return count; } public static int method2() { //靜態方法method2 count+=count; //訪問靜態變數count並賦值 System.out.println("在靜態方法 method2()中的 count="+count); //列印count return count; } public static void PrintCount() { //靜態方法PrintCount count+=2; System.out.println("在靜態方法 PrintCount()中的 count="+count); //列印count } public static void main(String[] args) { StaticMethod sft=new StaticMethod(); //通過例項物件呼叫例項方法 System.out.println("method1() 方法返回值 intro1="+sft.method1()); //直接呼叫靜態方法 System.out.println("method2() 方法返回值 intro1="+method2()); //通過類名呼叫靜態方法,列印coimt StaticMethod.PrintCount(); } }
執行該程式後的結果如下所示。
在靜態方法 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 虛擬機器在載入類時會執行靜態程式碼塊,如果類中包含多個靜態程式碼塊,則 Java 虛擬機器將按它們在類中出現的順序依次執行它們,每個靜態程式碼塊只會被執行一次。
- 靜態程式碼塊與靜態方法一樣,不能直接訪問類的例項變數和例項方法,而需要通過類的例項物件來訪問。
例 3
編寫一個 Java 類,在類中定義一個靜態變數,然後使用靜態程式碼塊修改靜態變數的值。最後在 main() 方法中進行測試和輸出。複製純文字複製
- public class StaticCode
- {
- public static int count=0;
- {
- count++;
- System.out.println("非靜態程式碼塊 count="+count);
- }
- static
- {
- count++;
- System.out.println("靜態程式碼塊 count="+count);
- }
- public static void main(String[] args)
- {
- System.out.println("*************** StaticCode1 執行 ***************");
- StaticCode sct1=new StaticCode();
- System.out.println("*************** StaticCode2 執行 ***************");
- StaticCode sct2=new StaticCode();
- }
- }
public class StaticCode { public static int count=0; { count++; System.out.println("非靜態程式碼塊 count="+count); } static { count++; System.out.println("靜態程式碼塊 count="+count); } public static void main(String[] args) { System.out.println("*************** StaticCode1 執行 ***************"); StaticCode sct1=new StaticCode(); System.out.println("*************** StaticCode2 執行 ***************"); StaticCode sct2=new StaticCode(); } }
如上述示例,為了說明靜態程式碼塊只被執行一次,特地添加了非靜態程式碼塊作為對比,並在主方法中建立了兩個類的例項物件。上述示例的執行結果為:
<pre class="info-box">靜態程式碼塊 count=1
*************** StaticCode1 執行 ***************
非靜態程式碼塊 count=2
*************** StaticCode2 執行 ***************
非靜態程式碼塊 count=3</pre>