Android Java中的static與final關鍵字的作用
static
1. static變量
按照是否靜態的對類成員變量進行分類可分兩種:一種是被static修飾的變量,叫靜態變量或類變量;另一種是沒有被static修飾的變量,叫實例變量。兩者的區別是:
對於靜態變量在內存中只有一個拷貝(節省內存),JVM只為靜態分配一次內存,在加載類的過程中完成靜態變量的內存分配,可用類名直接訪問(方便),當然也可以通過對象來訪問(但是這是不推薦的)。對於實例變量,沒創建一個實例,就會為實例變量分配一次內存,實例變量可以在內存中有多個拷貝,互不影響(靈活)。
2. static代碼塊
static代碼塊是類加載時,初始化自動執行的。如果static代碼塊有多個,JVM將按照它們在類中出現的先后順序依次執行它們,每個代碼塊只會被執行一次。
3. static方法
static方法可以直接通過類名調用,任何的實例也都可以調用,因此static方法中不能用this和super關鍵字,不能直接訪問所屬類的實例變量和實例方法(就是不帶static的成員變量和成員成員方法),只能訪問所屬類的靜態成員變量和成員方法。因為static方法獨立於任何實例,因此static方法必須被實現,而不能是抽象的abstract。
static方法只能訪問static的變量和方法,因為非static的變量和方法是需要創建一個對象才能訪問的,而static的變量/方法不需要創建任何對象。
********
static的數據或方法,屬於整個類的而不是屬於某個對象的,是不會和類的任何對象實例聯系到一起。所以子類和父類之間可以存在同名的static方法名,這里不涉及重載。所以不能把任何方法體內的變量聲明為static,例如:
fun() {
static int i=0; //非法。
}
其實理解static是只有一個存儲地方,而使用時直接使用,不需要創建對象,就能明白以上的注意事項。
另外,一般的類是沒有static的,只有內部類可以加上static來表示嵌套類。
final
在Java中聲明屬性、方法和類時,可使用關鍵字final來修飾。
final變量即為常量,只能賦值一次;
final方法不能被子類重寫;
final類不能被繼承。
1. final變量
聲明 final 字段有助於優化器作出更好的優化決定,因為如果編譯器知道字段的值不會更改,那么它能安全地在寄存器中高速緩存該值。final 字段還通過讓編譯器強制該字段為只讀來提供額外的安全級別。
其初始化可以在兩個地方,一是其定義處,也就是說在final變量定義時直接給其賦值,二是在構造函數中。這兩個地方只能選其一,要么在定義時給值,要么在構造函數中給值,不能同時既在定義時給了值,又在構造函數中給另外的值。
一旦被初始化便不可改變,這里不可改變的意思
對基本類型來說是其值不可變,而
對於對象變量來說其引用不可再變。
當函數參數為final類型時,你可以讀取使用該參數,但是無法改變該參數的值。
另外方法中的內部類在用到方法中的參變量時,此參變也必須聲明為final才可使用。
在java中,普通變量系統是自動初始化的,數值變量自動初始化為0,其余類型變量自動初始化為空。但是final類型的變量必須顯示初始化,且初始化的方法必須是在申明時或者在構造方法中直接賦值,而不能通過調用函數賦值。
2. final方法
如果一個類不允許其子類覆蓋某個方法,則可以把這個方法聲明為final方法。
使用final方法的原因有二:
第一、把方法鎖定,防止任何繼承類修改它的意義和實現。
第二、高效。編譯器在遇到調用final方法時候會轉入內嵌inline機制,大大提高執行效率。
注意,類中所有的private方法都被隱含是final的。由於無法取用private方法,則也無法重載之。
3. final類
final類不能被繼承,因此final類的成員方法沒有機會被覆蓋,默認都是final的。在設計類時候,如果這個類不需要有子類,類的實現細節不允許改變,並且確信這個類不會載被擴展,那么就設計為final類。
-----------------
特別要注意一個問題:
對於被static和final修飾過的實例常量,實例本身不能再改變了,但對於一些容器類型(比如,ArrayList、HashMap)的實例變量,不可以改變容器變量本身,但可以修改容器中存放的對象,這一點在編程中用到很多。
看個例子:
import java.util.ArrayList;
public class TestStaticFinal {
private static final String strStaticFinalVar = "aaa";
private static String strStaticVar = null;
private final String strFinalVar = null;
private static final int intStaticFinalVar = 0;
private static final Integer integerStaticFinalVar = new Integer(8);
private static final ArrayList<String> alStaticFinalVar = new ArrayList<String>();
private void test() {
System.out.println("-------------值處理前----------");
System.out.println("strStaticFinalVar=" + strStaticFinalVar + "");
System.out.println("strStaticVar=" + strStaticVar + "");
System.out.println("strFinalVar=" + strFinalVar + "");
System.out.println("intStaticFinalVar=" + intStaticFinalVar + "");
System.out.println("integerStaticFinalVar=" + integerStaticFinalVar + "");
System.out.println("alStaticFinalVar=" + alStaticFinalVar + "");
//strStaticFinalVar="哈哈哈哈";//錯誤,final表示終態,不可以改變變量本身.
strStaticVar = "哈哈哈哈"; //正確,static表示類變量,值可以改變.
//strFinalVar="呵呵呵呵"; //錯誤, final表示終態,在定義的時候就要初值(哪怕給個null),一旦給定后就不可再更改。
//intStaticFinalVar=2; //錯誤, final表示終態,在定義的時候就要初值(哪怕給個null),一旦給定后就不可再更改。
//integerStaticFinalVar=new Integer(8); //錯誤, final表示終態,在定義的時候就要初值(哪怕給個null),一旦給定后就不可再更改。
alStaticFinalVar.add("aaa"); //正確,容器變量本身沒有變化,但存放內容發生了變化。這個規則是非常常用的,有很多用途。
alStaticFinalVar.add("bbb"); //正確,容器變量本身沒有變化,但存放內容發生了變化。這個規則是非常常用的,有很多用途。
System.out.println("-------------值處理后----------");
System.out.println("strStaticFinalVar=" + strStaticFinalVar + "");
System.out.println("strStaticVar=" + strStaticVar + "");
System.out.println("strFinalVar=" + strFinalVar + "");
System.out.println("intStaticFinalVar=" + intStaticFinalVar + "");
System.out.println("integerStaticFinalVar=" + integerStaticFinalVar + "");
System.out.println("alStaticFinalVar=" + alStaticFinalVar + "");
}
public static void main(String args[]) {
new TestStaticFinal().test();
}
}
public class TestStaticFinal {
private static final String strStaticFinalVar = "aaa";
private static String strStaticVar = null;
private final String strFinalVar = null;
private static final int intStaticFinalVar = 0;
private static final Integer integerStaticFinalVar = new Integer(8);
private static final ArrayList<String> alStaticFinalVar = new ArrayList<String>();
private void test() {
System.out.println("-------------值處理前----------");
System.out.println("strStaticFinalVar=" + strStaticFinalVar + "");
System.out.println("strStaticVar=" + strStaticVar + "");
System.out.println("strFinalVar=" + strFinalVar + "");
System.out.println("intStaticFinalVar=" + intStaticFinalVar + "");
System.out.println("integerStaticFinalVar=" + integerStaticFinalVar + "");
System.out.println("alStaticFinalVar=" + alStaticFinalVar + "");
//strStaticFinalVar="哈哈哈哈";//錯誤,final表示終態,不可以改變變量本身.
strStaticVar = "哈哈哈哈"; //正確,static表示類變量,值可以改變.
//strFinalVar="呵呵呵呵"; //錯誤, final表示終態,在定義的時候就要初值(哪怕給個null),一旦給定后就不可再更改。
//intStaticFinalVar=2; //錯誤, final表示終態,在定義的時候就要初值(哪怕給個null),一旦給定后就不可再更改。
//integerStaticFinalVar=new Integer(8); //錯誤, final表示終態,在定義的時候就要初值(哪怕給個null),一旦給定后就不可再更改。
alStaticFinalVar.add("aaa"); //正確,容器變量本身沒有變化,但存放內容發生了變化。這個規則是非常常用的,有很多用途。
alStaticFinalVar.add("bbb"); //正確,容器變量本身沒有變化,但存放內容發生了變化。這個規則是非常常用的,有很多用途。
System.out.println("-------------值處理后----------");
System.out.println("strStaticFinalVar=" + strStaticFinalVar + "");
System.out.println("strStaticVar=" + strStaticVar + "");
System.out.println("strFinalVar=" + strFinalVar + "");
System.out.println("intStaticFinalVar=" + intStaticFinalVar + "");
System.out.println("integerStaticFinalVar=" + integerStaticFinalVar + "");
System.out.println("alStaticFinalVar=" + alStaticFinalVar + "");
}
public static void main(String args[]) {
new TestStaticFinal().test();
}
}
輸出結果
-------------值處理前----------
strStaticFinalVar=aaa
strStaticVar=null
strFinalVar=null
intStaticFinalVar=0
integerStaticFinalVar=8
alStaticFinalVar=[]
-------------值處理后----------
strStaticFinalVar=aaa
strStaticVar=哈哈哈哈
strFinalVar=null
intStaticFinalVar=0
integerStaticFinalVar=8
alStaticFinalVar=[aaa, bbb]