static關鍵字是擺在剛入行編程語言的小白們面前的一道難題,爲何要用static?使用它有什麼好處?修飾方法和修飾變量有什麼區別?本文將就java中static關鍵字的使用方法及注意事項進行深刻探討,一是爲了方便本身之後查閱,二也爲了與你們交流分享學習的經驗。java
static表示靜態,經常使用來修飾成員變量、成員方法、代碼塊和內部類,存放在方法區,做用在於建立獨立於對象存在的域變量或方法,當類被加載時,被static修飾的變量或方法就能夠經過類名進行訪問,當建立多個對象時,被static修飾的變量/方法不會所以創建多個數據。面試
咱們經過下面一段代碼來解釋一下它的功能:編程
public class Demo1 { public static void main(String[] args) { Test.p="靜態變量賦值了"; Test.say(); new Test(); } } class Test{ Test(){ System.out.println("構造方法執行了"); } static String p ; static{ System.out.println("靜態代碼塊執行了"); } public static void say(){ System.out.println("靜態方法執行了"); System.out.println(p); } public void say2(){ System.out.println("方法執行了"); System.out.println(p); } }
代碼中咱們分別使用關鍵字static定義了靜態變量、靜態代碼塊和靜態方法,執行結果以下編程語言
咱們發現,最早執行的語句是static修飾的代碼塊,在咱們經過類名直接調用方法say以前就執行了,隨後是咱們經過類名訪問的靜態方法say,最後纔是構造方法。到這裏小白可能會問,爲何咱們尚未建立對象就能夠訪問類中的內容呢?這就涉及到了關鍵字static的使用方法。性能
被static修飾的變量和方法咱們統稱爲靜態變量和靜態方法,屬於類的靜態資源,是類實例之間共享的,簡單地說,即不隨着建立對象的改變而發生改變。以普通變量和方法爲例:咱們寫一段簡單的代碼學習
public class Demo1 { public static void main(String[] args) { Test t1 = new Test(); Test t2 = new Test(); t1.p = "變量賦值了"; t1.x =1; t2.x =2; t1.say(); } } class Test{ String p; static int x; void say(){ System.out.println("方法執行了"); System.out.println(p); System.out.println(x); } }
這段代碼很簡單,即咱們經過建立的對象t來訪問Test類中的內容,與上一段代碼不一樣的是咱們不能經過類名的方式來直接調用這些變量方法,如Test.p和Test.say,而是要經過建立的新對象t。可是咱們卻能夠用對象t來訪問靜態變量x,可是變量x的內容屬於類,對象t1,t2是共享一個變量x的,經過兩個對象賦值後,結果取最後賦的值,因此輸出的結果以下。優化
靜態靜態塊也是static的重要應用之一。一般使用於類的初始化,和靜態變量、靜態方法同樣,靜態塊裏面的代碼只執行一次,且只在初始化類的時候執行。
爲了更清楚地描述靜態代碼塊的功能,咱們編寫以下代碼。this
public class Demo1 { public static void main(String[] args) { new Test2(); new Test1(); } } class Test2 extends Test1{ static{ System.out.println("靜態代碼塊1執行了"); } static{ System.out.println("靜態代碼塊2執行了"); } } class Test1{ static { System.out.println("靜態代碼塊3執行了"); } }
不難看出,靜態代碼塊隨着對象的建立,或者說類的實例化而進行,且只進行一次,咱們建立了兩個對象,可是每一個語句只打印了一次。咱們根據他們打印的順序能夠推斷出靜態代碼塊的執行規則。
1.按照父類到子類的順序執行。
2.在同一個類中按照代碼的順序執行
3.每一個靜態代碼塊只執行一次
靜態代碼塊能夠優化程序性能,正是由於它的特性:只會在類被初次加載的時候執行一次。spa
static正常狀況下是不能用來修飾類的,它只能修飾內部類,也就是咱們說的靜態內部類,它的應用場景相對於以上兩個功能少得多,一般咱們使用內部類時會保存一個引用,引用是指向建立它的外圍內,可是靜態內部類卻沒有。沒有這個引用就意味着:
一、它的建立是不須要依賴外圍類的建立。
二、它不能使用任何外圍類的非static成員變量和方法。
咱們經過代碼示例來簡單地介紹一下靜態內部類使用方法code
package com.java.demo1; public class Demo1 { public static void main(String[] args) { Test.Test2 t = new Test.Test2(); t.say(); } } class Test { static class Test2 { void say(){ System.out.println("靜態內部類"); } } }
好了,說到這裏,可能一些初學者會問,爲何要使用靜態呢?首先咱們總結一下被靜態static修飾的變量/方法/方法塊/類的特色
靜態修飾的特色
1.被static修飾的變量/方法是獨立與類所建立的對象而存在的,簡而言之,當咱們建立多個對象實例時,static修飾的變量/方法是被它們所共享的,即不隨着不一樣對象的建立而發生改變。
2.static在類加載時就建立好了內存空間,可是它的內容是能夠改變的,咱們能夠經過不一樣的對象給它賦值,可是它的值取決於你最終給它的賦值。
3.即使不建立對象,static修飾的變量或方法也是能夠存在的,當一個類加載完畢後,類中static修飾的變量和方法就能夠進行訪問。
靜態修飾的優勢
1.方便在咱們沒有建立對象時,調用類中的方法/變量
2.static能夠用來修飾類的成員方法、成員變量或編寫static代碼塊,可以有效地優化程序性能
咱們能夠經過下面一段代碼來直觀地感覺一下
package com.java.demo1; public class Demo1 { public static void main(String[] args) { Test t1 = new Test(); Test t2 = new Test(); Test t3 = new Test(); t1.name = "張三"; t2.name = "李四"; t3.name = "王麻子"; t1.age = 18; t2.age = 18; t3.age = 19; Test.school = "清華大學"; t1.say(); t2.say(); t3.say(); } } class Test { String name; int age; static String school; void say(){ System.out.println("我是"+name+",今年"+age+"歲,就讀於"+school); } }
運行結果以下
對於三個對象,他們的school屬性是徹底相同的,所以爲了避免佔用過多內存,咱們用static把變量school修飾成靜態變量,若是咱們發現變量school的內容寫錯了,也能夠經過一次修改就達成修改全部對象的目的。
介紹完了static的優勢,接下來講一些使用static關鍵字時常常出現的錯誤和須要你們注意的一些細節。
不少初學者容易把java中的static和C/C++中的static搞混了,在C/C++中,static可以改變成員的訪問權限,而這在java中時不行的,在java中只能經過四個權限修飾符來改變成員的訪問權限
如圖所示,咱們直接給private封裝的變量school賦值時,會提示錯誤。
這一點是初學者常常犯的錯誤,當咱們定義了一個非靜態的變量/方法後,若是咱們經過靜態的變量或方法來訪問非靜態的資源時程序是會報錯的。這其實不難理解,咱們以前說過,靜態修飾的變量/方法在類初始化時加載,它們的建立順序是在非靜態資源以前的,咱們用已經建立的資源去訪問沒有被建立的資源,這顯然是不合理的。但反過來,非靜態資源/靜態資源則是能夠訪問靜態資源的。咱們經過代碼來直觀地感覺一下。
雖然咱們以前提到過,靜態的資源自己是獨立於實例化的對象而存在的,可是咱們卻能夠經過對象來訪問靜態的資源,全部的靜態方法和靜態變量均可以經過對象訪問(只要訪問權限足夠)。咱們再經過一個案例來感覺:
public class Demo1 { public static void main(String[] args) { Test t = new Test(); t.say(); } } class Test { static int num = 1; void say(){ int num = 2; System.out.println(this.num); } }
結果輸出爲1,代碼中的this.num並無指向方法say中定義的num,這裏的this仍是指向了Test類,顯然咱們是能夠經過對象自己來訪問靜態資源的。
你們看完有什麼不懂的能夠在下方留言討論,也能夠關注我私信問我,我看到後都會回答的。也歡迎你們關注個人公衆號:前程有光,立刻金九銀十跳槽面試季,整理了1000多道將近500多頁pdf文檔的Java面試題資料放在裏面,助你圓夢BAT!文章都會在裏面更新,整理的資料也會放在裏面。謝謝你的觀看,以爲文章對你有幫助的話記得關注我點個贊支持一下!