Java Static關鍵字詳解
先思考兩個問題:
1.為什麽要使用Static關鍵字?
2.加了Static關鍵字修飾後會有什麽不同?
Static
一.為什麽要使用Static關鍵字?
這裏摘錄一下《Java編程思想(第四版)》裏關於static關鍵字的一段原話:(P29)通常來說,當創建類時,就是在描述那個類的對象的外觀與行為。除非用new創建那個對象,否則,實際上並未獲得任何對象。執行new來創建對象的時候,數據存儲空間才被分配,其方法才供外界調用。有兩種情形用上述方法是無法解決的。一種情形是,只想為某特定域分配單一存儲空間,而不去考慮究竟要創建多少個對象,甚至根本不需要創建任何對象。另一種情形是,希望某個方法不與包含他的類的任何對象關聯在一起。也就是說,即使沒有創建對象,也能夠調用方法
。簡單來說,static的主要目的就是創建獨立於具體對象的域變量與方法。
二.加了Static關鍵字修飾會有什麽不同?
1.this不能調用被static修飾的屬性字段。
因為被static修飾的會在類加載的時候初始化,被稱為類級變量(屬於類);而類的實例是在運行的時候初始化,屬於對象級變量(屬於對象)。
this是指當前對象的實例,super是指父類對象的實例。this(super)不能調用被static修飾的屬性字段的原因:jvm有類加載器,第一次加載時執行static域,jvm會專門劃分一個內存區域給static程序塊,所以什麽時候都可以調用這個被static修飾的屬性字段或者方法,屬於類。this指針是指向類的對象,在實例化對象時候jvm會在堆區分配給一個具體對象,this指向該對象。所以在靜態方法中不能調用非靜態屬性或者方法
2.static修飾屬性和方法
1.static修飾屬性時候,即所有該類對象共享一份存儲空間。
public class StaticTest { public static int staticA; public int A; public static void main(String[] args){ StaticTest test; StaticTest A1=new StaticTest(); StaticTest A2=new StaticTest(); A1.staticA++; A2.staticA++; A1.A++; A2.A++; System.out.println("StaticAInfo:"+A1.staticA+" "+A2.staticA); System.out.println("AInfo"+A1.A+" "+A2.A); } } /** 運行結果 * StaticAInfo:2 2 * AInfo1 1 **/
即static修飾的不是某個具體對象所有,而是該類所有對象共有的,StaticTest.staticA只有一份存儲空間。
2.static修飾方法時候,類和對象都能調用該方法,沒有被static修飾的方法只能被實例化對象調用。
public class StaticTest { public static void staticTest(){ } public void test(){ } public static void main(String[] args){ StaticTest.staticTest(); //StaticTest.test(); 該調用是錯誤的 StaticTest test=new StaticTest(); test.staticTest(); test.test(); } }
static修飾成員方法最大的作用,就是可以使用"類名.方法名"的方式操作方法,避免了先要new出對象的繁瑣和資源消耗,一個static修飾的類中,不能使用非static修飾的成員變量和方法,這很好理解,因為static修飾的方法是屬於類的,如果去直接使用對象的成員變量,它會不知所措(不知該使用哪一個對象的屬性)。
static修飾成員方法的時候最大的好處是可以節省new一個對象的開銷,即可以直接通過類來調用方法。
3.static修飾內部類
一般用的比較少只能用來修飾內部類,一個static修飾的內部類中,不能使用非static修飾的成員變量和方法,這很好理解,因為static修飾的方法是屬於類的,如果去直接使用對象的成員變量,它會不知所措(不知該使用哪一個對象的屬性)。
4.靜態塊
class Book{ public Book(String msg) { System.out.println(msg); } } public class Person { Book book1 = new Book("book1成員變量初始化"); static Book book2 = new Book("static成員book2成員變量初始化"); public Person(String msg) { System.out.println(msg); } Book book3 = new Book("book3成員變量初始化"); static Book book4 = new Book("static成員book4成員變量初始化"); public static void funStatic() { System.out.println("static修飾的funStatic方法"); } public static void main(String[] args) { Person.funStatic(); System.out.println("****************"); Person p1 = new Person("p1初始化"); } /**Output * static成員book2成員變量初始化 * static成員book4成員變量初始化 * static修飾的funStatic方法 * *************** * book1成員變量初始化 * book3成員變量初始化 * p1初始化 *///~ }
在上面的例子中我們可以發現兩個有意思的地方,第一個是當我們沒有創建對象,而是通過類去調用類方法時,盡管該方法沒有使用到任何的類成員,類成員還是在方法調用之前就初始化了,這說明,當我們第一次去使用一個類時,就會觸發該類的成員初始化。第二個是當我們使用了類方法,完成類的成員的初始化後,再new該類的對象時,static修飾的類成員沒有再次初始化,這說明,static修飾的類成員,在程序運行過程中,只需要初始化一次即可,不會進行多次的初始化。
class Book{ public Book(String msg) { System.out.println(msg); } } public class Person { Book book1 = new Book("book1成員變量初始化"); static Book book2; static { book2 = new Book("static成員book2成員變量初始化"); book4 = new Book("static成員book4成員變量初始化"); } public Person(String msg) { System.out.println(msg); } Book book3 = new Book("book3成員變量初始化"); static Book book4; public static void funStatic() { System.out.println("static修飾的funStatic方法"); } public static void main(String[] args) { Person.funStatic(); System.out.println("****************"); Person p1 = new Person("p1初始化"); } /**Output * static成員book2成員變量初始化 * static成員book4成員變量初始化 * static修飾的funStatic方法 * *************** * book1成員變量初始化 * book3成員變量初始化 * p1初始化 *///~ }
Java Static關鍵字詳解