1. 程式人生 > >final與static變數

final與static變數

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來表示巢狀類。 其實,我們只需要明白用static修飾的變數是屬於整個類的。但是如果你在一個用static修飾的塊中定義一個靜態的變數,那麼這個變數就應該是屬於整個類的,但是很明顯,並不是這樣。在這個塊中的變數明顯只能是屬於這個塊自身而已,並不是屬於整個類的,因此不能在一個靜態的塊中定義一個靜態的變數。當然在靜態的塊中,也只能使用已經定義好的靜態的屬性和方法,不能使用不是靜態的屬性和方法。

final

    特別要注意的是,在程式設計中會經常使用final來修飾容器變數。用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();
        }
}   輸出結果 -------------值處理前---------- strStaticFinalVar=aaa strStaticVar=null strFinalVar=null intStaticFinalVar=0 integerStaticFinalVar=8 alStaticFinalVar=[] -------------值處理後---------- strStaticFinalVar=aaa strStaticVar=哈哈哈哈 strFinalVar=null intStaticFinalVar=0 integerStaticFinalVar=8

alStaticFinalVar=[aaa, bbb]

本文轉自http://blog.csdn.net/mamingminger/article/details/25792639