本節介紹JAVA里static和final的作用和使用方法以及一些需要注意的問題.
一、static
static表示"全局"或"靜態",用來修飾成員變量和成員方法,以及代碼塊.
被static修飾的成員變量和成員方法獨立於該類的任何對象.也就是說,它不依賴類特定的實例,被類的所有實例共享.只要這個類被加載,JAVA虛擬機就能根據類名在運行時數據區的演繹法我內找到它們.因此,static對象可以在它的任何對象創建之前訪問,無需引用任何對象.
用public修飾的static成員變量和成員方法本質是全局變量和全局方法,當聲明它類的對象時,不生成static變量的副本,而是類的所有實例共享同一個static變量.
static變量前可以有private修飾,表示這個變量可以在類的靜態代碼塊中,或者類的其它靜態成員方法中使用(當然也可以在非靜態成員方法中使用--廢話).但是不能在其它類中通過類名來直接引用,這一點很重要.實際上只要搞明白,private是訪問權限限定,static表示不要實例化就可以使用,這樣就容易理解了.static前面加上其它訪問權限關鍵字的效果也以此類推.
static修飾的成員變量和成員方法習慣上稱為靜態變量和靜態方法,可以直接通過類名來訪問,訪問語法為:
類名.靜態方法名(參數)
類名.靜態變量名
用static修飾的代碼塊表示靜態代碼塊,當java虛擬機(JVM)加載類時,就會執行該代碼塊.
1. static變量
按照是否靜態可把成員變量分為兩類:被static修飾的靜態變量和沒有被static修飾的實例變量.
兩者的區別是:
對於靜態變量在內在中只有一個拷貝(節省內存),JVM只為靜態變量分配一次內存,在加載類的過程中完成靜態變量的內存分配,可用類名直接訪問(方便),當然也可以通過對象來訪問(不推薦).
對於實例變量,每創建一個實例,就會為實例變量分配一次內存,實例變量可以在內在中有多個拷貝,互不影響(靈活).
所以一般在需要實現以下兩個功能時使用靜態變量:
*在對象之間共享值時
*方便訪問變量時
比如有一個Empoyee員工類,每一個員工都有一個屬於他自己的標識碼id,但我們希望每當添加一個新員工的時候都給他賦一個新的標識碼.這時,每個員工自己的標識碼屬於員工自己,也就是屬於每個員工對象.但必須有一個獨立於每個員工的標識碼用來給新員工賦標識碼,這時我們就要設定一個實例域(非靜態)id和靜態域(靜態變量)nextID:
在上面的代碼中,類Employee中有一個實例域(非靜態)id和一個靜態域nextID.實例域id是屬於每一個員工的,但靜態域nextID則是屬於類的,它不屬於哪一個員工, 它屬於類Employee,每當有新員工被添加時,nextID就加1,從而可以給新來的員工賦新的標識碼.
static是用來標識全局共用的變量,即使沒有一個員工,nextID仍然存在.
*有時我們會需要用到靜態常量,比如常數PI,它是一個常量,不能被修改,但可以被全局調用,這時需要用static final來修飾:
這樣定義了之后,我們就可以用Math.PI來調用PI這個常量,並且PI不能被修改.
2. 靜態方法
靜態方法可以直接通過類名調用,任何的實例也都可以調用.
因此,靜態方法中不能用this和super關鍵字,不能直接訪問所屬類的實例變量和實例方法(即非靜態變量和非靜態方法),只能訪問所屬類的靜態成員變量和成員方法.因為實例成員與特定的對象關聯!
但這並不是絕對的,如果想要在static方法中調用非靜態的變量或者方法,可以先實現你所想要調用的非靜態變量或方法所在的類的對象,然后通過個這對象的引用就可以訪問非靜態的方法和成員.
因為static方法獨立於任何實例,因此static方法必須被實現,而不能是抽象的abstract.
例如,為了方便方法的調用,JAVA API中的Math類中的所有方法都是靜態的,而一般類內部的static方法也是方便其它類對該方法的調用.
靜態方法是類內部的一類特殊方法,只有在需要時才將對應的方法聲明成靜態的,一個類內部的方法一般都是非靜態的.
3. static代碼塊
static代碼塊也叫靜態代碼塊,是在類中獨立於類成員的static語句塊,可以有多個,位置可以隨便放,它不在任何的方法體內,JVM加載類時會執行這些靜態的代碼塊,如果static代碼塊有多個,JVM將按照它們在類中出現的先后順序依次執行它們,每個代碼塊只會被執行一次.
利用靜態代碼塊可以對一些static變量進行賦值.
二、final
- final變量的值不能被改變
- final的成員變量
- final的局部變量
- final的方法不能被重寫
- final的類不能被繼承
static final ...
static final用來修飾成員變量和成員方法,可簡單理解為"全局變量".
對於變量,表示一旦給值就不可修改,並且通過類名可以訪問.
對於方法,表示不可覆蓋,並且可以通過類名直接訪問.
有時你希望定義一個類成員,使它的使用完全獨立於該類的任何對象.通常情況下,類成員必須通過它的類的對象訪問,但是可以創建這樣一個成員它能夠被它自己使用,而不必引用任何對象.你可以將方法和變量都聲明為static,static成員的最覺的例子是main(),困為在程序開始執行時必須調用main(),所以它被聲明為static.
聲明為static的變量實質上就是全局變量。當聲明一個對象時,並不產生static變量的拷貝,而是該類所有的實例變量共用同一個static變量。聲明為static的方法有以下幾條限制:
•
它們僅能調用其他的static 方法。
•
它們只能訪問static數據。
•
它們不能以任何方式引用this 或super(關鍵字super 與繼承有關,在下一章中描述)。
如果你需要通過計算來初始化你的static變量,你可以聲明一個static塊,Static 塊僅在該類被加載時執行一次。