遞推演算法題:令人費解的開關『拉燈』
1.static存在的意義
1.static可以建立獨立於具體域物件的變數或者方法,這個方法或者變數不與包含它所對應的類的任何物件包含在一起。也就是說即使沒有建立物件,也可以呼叫這個變數或者方法
2.static可以用來形成靜態程式碼塊來優化程式效能。static塊可以存放在類的任何一個地方,當類進行載入時,會按照static塊的順序來進行載入,並且只會載入一次。
3.static可以為某特定域分配單一儲存空間,而不去考慮究竟要建立多少物件,甚至根本就不建立物件。(一個static欄位對每個類來說都只有一份儲存空間,而非static欄位則是對每個物件都有一個儲存空間)
2.static的特點
1.被static修飾的變數或者方法獨立於該類的任何物件,可以理解成這些變數或者方法不屬於任何一個例項物件,是被類中所有物件所共享。
2.在一個類第一次載入的時候,就會載入static修飾的部分,而且只在類第一次使用時載入並進行初始化。
3.static變數值在第一次載入的時候就分配了空間,以後建立物件時不會再進行重新分配空間,但是可以賦值。
4.被static修飾的變數或者方法是優先於物件的,也就是說,即使你沒有建立物件,也可以呼叫static修飾的變數或者方法。
3.static的應用場景
3.1修飾成員變數
成員變數是可以被類中所有物件所共享的,當一個成員變數被static所修飾,那麼這個變數就成了靜態變數
靜態變數和例項變數有點區別,首先沒有被static修飾的成員變數叫做例項變數,例項變數屬於這個類的例項物件,也就是說,可以通過建立物件來對它進行呼叫。兩者之間的區別是,靜態變數不屬於任何例項物件,它是屬於類的。在類載入的時候進行分配一次記憶體空間。例項變數是每次建立物件時,都會為成員變數分配記憶體空間。
3.2修飾成員方法
被static修飾的方法叫做靜態方法,其實main方法就是一個靜態方法。靜態方法可以直接被呼叫,也就是類名.方法名()的方式。
3.3靜態程式碼塊
也就是在類中被static包裹的一部分程式碼,形如static{}
public class staticTest {public staticTest(){ System.out.println("staticTest:構造器初始化"); } { System.out.println("staticTest:初始化塊"); } static { System.out.println("staticTest:靜態初始化塊"); } } class staticTest1 extends staticTest{ public staticTest1(){ System.out.println("staticTest1:構造器初始化"); } { System.out.println("staticTest1:初始化塊"); } static { System.out.println("staticTest1:靜態初始化塊"); } } class staticTest2 extends staticTest1{ public staticTest2(){ System.out.println("staticTest2:構造器初始化"); } { System.out.println("staticTest2:初始化塊"); } static { System.out.println("staticTest2:靜態初始化塊"); } } class staticTest3 extends staticTest2{ public static void main(String[] args) { staticTest2 staticTest2 = new staticTest2(); System.out.println("------"); staticTest staticTest = new staticTest2(); } }
輸出:
"C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.3\jbr\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.3\lib\idea_rt.jar=65088:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.3\bin" -Dfile.encoding=UTF-8 -classpath D:\java\javase進階\.idea\out\production\Test staticTest3 staticTest:靜態初始化塊 staticTest1:靜態初始化塊 staticTest2:靜態初始化塊 staticTest:初始化塊 staticTest:構造器初始化 staticTest1:初始化塊 staticTest1:構造器初始化 staticTest2:初始化塊 staticTest2:構造器初始化 ------ staticTest:初始化塊 staticTest:構造器初始化 staticTest1:初始化塊 staticTest1:構造器初始化 staticTest2:初始化塊 staticTest2:構造器初始化 Process finished with exit code 0
可以看出:靜態程式碼塊只初始化一次。
3.4靜態內部類
1.靜態內部類不可以訪問外部類非靜態成員。
2.靜態內部類不需要建立外部類的物件就可以訪問。
3.靜態內部類可以有多種許可權訪問型別。
public class Myself { private static String name = "業平"; private String sex = "男"; //靜態內部類可以為public修飾 public static class Person{ //靜態內部類可以定義非靜態變數 private String address = "山東"; private static String high = "180"; //內部類公用成員 public String age = "20"; public void disPlay(){ //不能訪問外部類非靜態成員 //System.out.println(sex); //可以訪問靜態成員 System.out.println(name); //訪問本內部類成員 System.out.println(address); } } public void play(){ //外部類訪問內部類非靜態成員需要例項化 Person person = new Person(); person.disPlay(); //System.out.println(high); //System.out.println(age); System.out.println(person.age); System.out.println(person.address); } public static void main(String[] args) { Myself myself = new Myself(); myself.play(); } }
輸出:
業平 山東 20 山東