標籤:ext 設計 ide 改變 父類 載入 空間 大寫 例子
static關鍵字的用法
static的意思是“’靜態”,在java裡面可用於修飾屬性和方法。
static關鍵字的應用應注意以下幾種情形:
1.static作用於某個欄位,一個static欄位對每個類來說只有一份儲存空間,而非static欄位是每個對象有一份儲存空間。
2.static作用於方法的重要用法是不需要建立任何對象直接調用該static方法,這對於main()方法很重要。
3.static不能應用於局部變數。
4.Java中禁止使用全域方法,所以引入static方法通過類本身來直接調用。
package cn.wangze.test;class Demo{ public static int i = 19;}public class staticDemo { private static Demo demo1 = new Demo(); private static Demo demo2 = new Demo(); public static void main(String[] args){ System.out.println(Demo.i); //19 System.out.println(demo1.i); //19 System.out.println(demo2.i); //19 demo1.i++; System.out.println(Demo.i); //20 System.out.println(demo1.i); //20 System.out.println(demo2.i); //20 Demo.i++; System.out.println(Demo.i); //21 System.out.println(demo1.i); //21 System.out.println(demo2.i); //21 }}
上面程式的輸出結果驗證了上面兩條,帶有static關鍵字的資料在記憶體中佔有一塊固定記憶體位址,你可以用類名直接調用,也可以建立對象來調用,推薦ClassName.method()來調用。當我們改變它的值,任何地方的調用也會隨之改變。
Java系統內建的Math、UUID、Class等常用的工具類就是用的這種方式。
為什麼要將方法和變數都寫成靜態。
因為,這些方法我只是想調用一下,不需要牽扯工具類中的任何屬性和變數,所以,我就沒有必要執行個體化了(new)。既然不需要執行個體化了,那麼就用靜態就行了。
你也可以在實際項目中根據業務需求來聲明自己的工具類,只需要加入static關鍵字,引入該類後使用類名.方法名()調用即可。
需要注意的一點是,類的載入和初始化過程中,帶有static的資料會最先載入並調用,其次是構造器的載入,最後才是普通成員變數和方法的載入。
final關鍵字的用法
final意味著"不可改變的",一般應用於資料、方法和類。
final資料
當資料是基本類型時,意味著這是一個永不改變的編譯時間常量,一個在運行時被初始化的值,你不希望它改變。
當資料是參考型別時,用static和final修飾表示這是只佔據一塊不能改變的記憶體空間。
有一條約定成俗的規定是使用stati和final修飾的變數即編譯期常量應該用全部大寫字母表示,例如:
package cn.wangze.test;import java.util.*;class Value{ int i; public Value(int i){ this.i = i; }}public class FinalData { private static Random rand = new Random(47); private String id; public FinalData(String id){ this.id = id; } private final int value_one = 9; private static final int VALUE_TWO = 99; public static final int VALUE_THREE = 39; private final int i4 = rand.nextInt(20); static final int INT_5 = rand.nextInt(20); private Value v1 = new Value(11); private final Value v2 = new Value(22); static final Value V3 = new Value(33); private final int[] a = {1,2,3,4,5,6}; @Override public String toString(){ return id+", i4="+i4+",INT_5 = "+INT_5; } public static void main(String[] args){ FinalData fd1 = new FinalData("fd1"); //fd1.value_one++; 錯誤,final修飾的基本類型資料的值不能改變 fd1.v2.i++; fd1.v1 = new Value(9); //可以操作,因為v1不是final資料 //fd1.v2 = new Value(0); 錯誤,final修飾的參考型別資料的記憶體位址不能改變 //fd1.v3 = new Value(5); 錯誤,final修飾的參考型別資料的記憶體位址不能改變 //fd1.a = new int[3]; /錯誤,final修飾的參考型別資料的記憶體位址不能改變 System.out.println(fd1); // fd1, i4=15,INT_5 = 18 System.out.println("creating new FinalData"); FinalData fd2 = new FinalData("fd2"); System.out.println(fd1); //fd1, i4=15,INT_5 = 18 System.out.println(fd2); //fd2, i4=13,INT_5 = 18 }}
上面例子驗證了final修飾的基礎資料型別 (Elementary Data Type)和引用資料類型的區別。根據i4和INT_5的輸出值可以得出結論,在編譯期我們不能因為資料是final 的就可以知道它的值,只有在運行時才會確定它的值。同時這裡也展示了靜態和非靜態區別,帶有static關鍵字的資料在裝載時被初始化,非靜態資料是在建立對象時間初識化的。例如:
package cn.wangze.test;class useDemo{ private int i; public useDemo(int ii){ i = ii; }}public class BlankFinal { private final int i = 9; private final int j; private final useDemo ud; public BlankFinal(){ j = 1; ud = new useDemo(10); } public BlankFinal(int x){ j = 2; ud = new useDemo(x); } public static void main(String[] args){ new BlankFinal(); new BlankFinal(55); }}
上面例子我們在定義final變數是沒有給其賦值,這並沒有錯,但是一定要在構造器中給其賦值,不然編譯都不會通過。
2、fianl參數
當我們把方法傳入的形參定義為fianl時候,代表我們並不想在方法內部改變此參數的引用。
public void change( final useDemo u2){ u2.i = 20; //u2 = new useDemo(20); 報錯 }
事實是當我們不帶有final關鍵字時,函數內部的引用改變也不會對外界的實參產生影響,所以我認為這裡final的作用是編譯期的阻攔,起到一個警示的作用。
3、fianl方法
一般我們使用final方法的目的就是防止子類對該類方法的覆蓋或修改。
類中的所有private方法都隱式的制定為final的。因為private方法只會在本類顯示,即使是子類也不能操作該方法。有時候我們在子類中聲明與父類private方法相同名稱的方法,這樣並不會報錯,實際上我們並沒有覆蓋或者修改父類的private 方法,它只是一個和父類private方法具有相同名稱的新方法。
4、fianl類
一般我們使用final類的目的就是說明我們不打算用任何類繼承該類,即不希望該類有子類。
帶有final關鍵字的類,其內部所有方法和資料都是隱式帶有final關鍵字的,因為沒有類可以繼承該類,代表著任何外界因素可以改變它的資料。
總結:
在我們設計程式的時候,會根據業務需求來決定是否對資料或方法或類帶有static和final關鍵字,這很重要,從另一個角度來說,final和static關鍵字的合理應用確實可以提高程式的效率,減少記憶體的消耗,當我們瞭解了類的初始化和載入過程,可能會對final和static有一個更加直觀的認識。
Java的static和final關鍵字的用法