1.靜態是什么?有什么用?
static的主要作用在於創建獨立於具體對象的域變量或者方法。
每創建一個對象,都會在堆里開辟內存,存成員(屬性),但是不存方法,方法是共用的,沒必要每一個對象都浪費內存去存方法。有一個叫方法區的地方,專門存方法。方法區里又有靜態域,存靜態變量或者靜態方法。
普通變量和方法的調用:通過對象調用
靜態變量和方法的調用:通過對象或類調用

public class MyTest8 { public static void main(String[] args) { System.out.println(Plant.name);//通過類調用 Plant p1=new Plant(); System.out.println(p1.name);//通過對象調用 p1.name="植物";//類似方法,是公用的,改了之后就是改了,新建對象也是這個值 Plant p2=new Plant(); System.out.println(p2.name);//通過對象調用 } } class Plant{ static String name="靜態植物"; public static void say() { System.out.println("植物類"); } } /**輸出 靜態植物 靜態植物 植物 */
在類被加載的時候,靜態的代碼都會被加載,並且只加載一次,放在方法區里,該類的對象一起用。省時省力。
2.加載類有什么用?
任何程序都要先加載到內存中才能和CPU進行交流,而JVM中的ClassLoader(類加載器)就是負責提前將,class文件加載到內存中去的。
3.類何時被加載?(普通人的宏觀理解)
- 實例化對象時,如Chinese c1=new Chinese();此時加載了Chinese類
- 通過類名調用靜態變量或靜態方法的時候
- 如果實例化子類對象,會先加載父類
通過代碼驗證:
public class MyTest8 { public static void main(String[] args) { Plant.say();//通過類名調用靜態方法 Plant p1 = new Plant();//創建對象 Plant p2 = new Plant(); } } class Plant{ static String name="靜態植物"; public static void say() { System.out.println("植物類"); } static { System.out.println("植物類的靜態代碼被執行加載了"); } { System.out.println("植物類的普通代碼被加載了"); } }
輸出:
植物類的靜態代碼被執行加載了
植物類
植物類的普通代碼被加載了
植物類的普通代碼被加載了
由此可知,Plant.say();調用方法時就加載了類,靜態代碼也都被執行了,並且只執行一次,創建對象的時候再次加載類,但是不執行靜態代碼,而是非靜態代碼。
再通過繼承關系觀察靜態和非靜態的關系
public class MyTest8 { public static void main(String[] args) { Flower.say();//通過類名調用靜態方法 Flower f1=new Flower();//創建花類對象 Flower f2=new Flower(); } } class Plant{ static String name="靜態植物"; public static void say() { System.out.println("植物類"); } static { System.out.println("植物類的靜態代碼被執行加載了"); } { System.out.println("植物類的普通代碼被加載了"); } } class Flower extends Plant{ static { System.out.println("花類被加載了"); } static String name="花"; public static void say() { System.out.println("花類"); } { System.out.println("花類的普通代碼被加載了"); } }
輸出:
植物類的靜態代碼被執行加載了
花類被加載了
花類
植物類的普通代碼被加載了
花類的普通代碼被加載了
植物類的普通代碼被加載了
花類的普通代碼被加載了
由此可知:調用靜態的東西,只執行靜態的代碼,靜態代碼只執行一次。創建對象的時候也會加載,如果靜態沒有被加載過也會被加載,加載過就不用。加載子類的時候,會先把父類加載一次。
在代碼中,調用子類靜態方法,則先加載父類的靜態代碼,再加載子類的靜態代碼,再調用方法。創建對象的時候,先加載父類,再加載子類。
類裝載的過程:
- 加載:根據查找路徑找到相應的 class 文件然后導入;
- 檢查:檢查加載的 class 文件的正確性;
- 准備:給類中的靜態變量分配內存空間;
- 解析:虛擬機將常量池中的符號引用替換成直接引用的過程。符號引用就理解為一個標示,而在直接引用直接指向內存中的地址;
- 初始化:對靜態變量和靜態代碼塊執行初始化工作。
牛客刷題
1.初始化代碼執行順序是:父類靜態→子類靜態→父類普通代碼塊→子類普通代碼塊→父類構造方法→子類構造方法
2.靜態方法屬於類不屬於對象;靜態方法中只能訪問其他靜態方法和靜態數據,不能訪問非靜態的。
3.靜態不可用this調用。