Java基礎系列-static關鍵字
原創文章,轉載請標註出處:《Java基礎系列-static關鍵字》
一、概述
static關鍵字是Java諸多關鍵字中較常使用的一個,從其本意可得其意:靜態,何為靜態呢?靜,即不動,靜止,固定不變之意(其實可以理解為儲存位置不變)。
Java中的靜是相對於“動”而言的,所謂的動就是可變化的內容。
當然這裡指的是針對類而言的,靜態內容指的是在類被JVM載入的時候就確定的內容,這部分內容只會被分配一次記憶體,即在記憶體中保留一份儲存,動態內容則不同,它們是隨類的物件建立而動的,每當建立一個物件的時候就會對這些內容分配一份記憶體,即每個物件都有自己獨有的記憶體儲存空間(其中儲存著那些動態的內容)。
靜態的內容是屬於類的,動態的內容屬於物件。
上面的描述是及其概括的描述,下面我們仔細的瞭解下static的作用。
二、作用
2.1 static修飾變數
static是一種修飾符,最常用的就是修飾變數,static修飾的變數含有全域性的意味,這個變數會變得脫穎而出,不再受物件的桎梏,它在類載入的時候就會分配記憶體來儲存,儲存在執行時資料區中的方法區中,屬於類級別的存在,可以使用類名點用。
如果我們在類StaticTest中定義一個如下的靜態變數:
public class StaticTest{ static int i = 1;//申明靜態變數 }
那麼我們就可以使用下面的方式進行使用:
public class StaticTest{ static int i = 1;//申明靜態變數 public static void main(String[] args){ StaticTest.i = 3;//類名點用 } }
靜態變數可被其他方法直接呼叫,因為靜態變數早於或同於其他變數、方法而存在,故而可被隨意使用,但非靜態變數不可以,因為非靜態變數屬於物件,需要在物件建立的時候才能分配記憶體而存在,明顯在物件建立之前靜態方法就無法直接呼叫非靜態變數(因為尚不存在這個變數),當然在建立了物件之後就可以呼叫了,為了確保正確性,一律規定在靜態方法中不能直接呼叫非靜態變數,所有的非靜態變數必須使用物件來呼叫。
何時使用static變數呢?
根據static變數的儲存方式,我們可以看出,這種變數只會存在一份,但卻可以被任意使用,可以被所有的物件所擁有,它的值的可變的,但卻是共享的,一方改變,多方共享。
那麼我們不難想到,我們在定義類的時候對於那些公共的、共享的屬性完全可以定義成static的,這樣一來,不但節省的記憶體消耗,而且操作性也變得非常容易,需要修改的時候,只需要修改一個,那麼所有物件都會得到這個修改後的新值。
2.2 static修飾常量
常量是被final所修飾的變數的別稱,final修飾變數之後,表示這個變數的值一旦賦值,則不再發生改變。如果在加上static修飾,那麼這個變數就會變成一個靜態常量(類常量),這個常量會在類載入時分配記憶體到方法區中。而僅使用final修飾的常量則是在物件建立時儲存到方法區中。因為他屬於物件的常量,而靜態常量是屬於公共的、共享的常量。
具體可以檢視《Java基礎系列--final、finally關鍵字》
2.3 static修飾方法
static修飾方法表示這些方法為靜態方法,靜態方法和非靜態方法一樣都儲存在方法區中,不同之處在於動靜之分,靜態方法中不能直接呼叫非靜態變數和方法。靜態方法自身屬於類級存在,可以使用類名點用。
近來,static方法一般用於定義工具方法,一般在一個工具類中定義,這個類內部全部為靜態內容,完全作為一個工具對外進行服務(這貌似有些違背面向物件設計思想)。
2.4 static修飾程式碼塊
程式碼塊的存在,一般用於初始化一些變數的值,非靜態程式碼塊用於初始化非靜態變數的值,該程式碼塊在每次建立物件時都會被呼叫,而靜態程式碼塊用於初始化一些靜態變數的值,只會在類載入的時候呼叫執行一次。
詳情見
《JVM基礎系列-類載入器》
2.5 static修飾內部類
內部類種類較多,這裡講靜態內部類,靜態內部類由於其靜態特性,可脫離外部類來建立物件,普通內部類必須依據外部類物件來建立內部類物件。
靜態內部類中可呼叫外部類中的靜態內容,其中包括private內容。
class Invoke{ static int i = 1; int j = 2; static class InnerClass1{ public void innerMethod(){ i = 3; new Invoke().j = 4; outMethod1(); //outMethod2();//報錯 //j = 4;//報錯 } } class InnerClass2{ public void innerMethod(){ i = 3; outMethod1(); outMethod2(); j = 4; } } static void outMethod1(){} void outMethod2(){} }
我們需要使用如下方式建立內部類的物件:
public class StaticTest { public static void main(String[] args){ Invoke.InnerClass1 innerClass1 = new Invoke.InnerClass1();// 3- Invoke.InnerClass2 innerClass2 = new Invoke().new InnerClass2();//4- } }
注意第3、4行的建立方式的區別。
靜態內部類和普通內部類的區別:
- 靜態內部類可以有靜態成員(方法,屬性),而非靜態內部類則不能有靜態成員(方法,屬性)。
- 靜態內部類只能夠訪問外部類的靜態成員,而非靜態內部類則可以訪問外部類的所有成員(方法,屬性)。
2.6 static匯入
靜態匯入功能是一種較新的功能,可以單獨匯入某個類中的靜態方法。
import static java.util.Collections.*; import static java.util.Collections.synchronizedList;
如上第一行表示匯入Collections類中的所有靜態方法,而第二行僅僅匯入指定的靜態方法synchronizedList()。