01
在使用控制面板時的實質:
Hello.java
使用javac
,然後變成爲Hello.class
通過運行java
這個命令,在類加載器中(含有加載,驗證,準備,解析,初始化,使用,卸載),到jvm
爲Java虛擬機中運行,在jvm
中有方法區,堆內存,線程棧,本地方法棧,PC
計數器。
類加載器:
加載,
驗證,
class
文件的版本是否能兼容當前的Java
虛擬機版本,然後class
文件要滿足虛擬機的規範。準備,需要準備什麼呢?就是要進行類成員的初始化爲初始值,其中爲
final
修飾的類變量除外,final
變量就直接初始化爲變量值,而類成員不一樣。解析,什麼是解析呢?就是把符號引用解析爲直接引用,就是我們變量
xxx
,這種代表變爲直接引用,什麼是直接引用呢?就是內存地址,如我們常見的xxx0203r0e
,這種。初始化,把關於
static
修飾的變量或者是static
靜態代碼塊按照順序組成構造器進行初始化變量。使用,
卸載
JVM
JVM:
方法區(保存所有類的信息,通過常量池來保存生成所有類信息的對象),堆內存,線程棧,本地方法棧,計數器。
// 在控制面板中,反編譯javap -c xxx 就是將字節碼反編譯爲字節碼的指令輸出
public class Hello{ public Hello(); Code: 0: aload_0 1: invokespecial #1 4: return public static void main(java.lang.String[]); ... }
把程序放進jvm
中運行,到線程棧中運行,主方法main
(主線程),在線程棧中運行如果有遇到new
對象關鍵字時,main
這個主線程就會在自己的內存中(線程棧)聲明一個的對象(對象的引用指向堆內存中開闢的對象),Hello hello
;在jvm
中有個堆內存,就會申請一片空間內存地址,即創建一個對象,實例變量,實例方法從方法區中指向堆內存。
public class Hello{ public static void main(String[] args){ Hello hello = new Hello(); // 對象的聲明 和 創建對象 } }
類加載到虛擬機中:
public class Demo static { System.out.println("靜態代碼塊"); } { System.out.println("普通代碼塊"); } public Demo(){ System.out.println("構造方法"); } public static void main(String[] args){ new Demo(); } }// 結果靜態代碼塊 普通代碼塊 構造方法// 加載 驗證 準備 解析 初始化 使用 卸載Demo.java -> Demo.class -> 加載進入虛擬機中,類加載器 (驗證類信息,元素信息,版本,字節碼,準備,初始化類變量,解析把符號引用解析爲直接引用,進行初始化就是把static變量和static靜態代碼塊進行初始化變量)
步驟:
在堆內存中執行的順序就是加載實例信息,然後在進行構造方法。
02
瞭解static案例
// 父類public class F static { System.out.println("F靜態代碼塊"); } { System.out.println("F普通代碼塊"); } public F(){ System.out.println("F構造方法"); } }// 子類public class S extends F static { System.out.println("S靜態代碼塊"); } { System.out.println("S普通代碼塊"); } public S(){ super(); // 默認的 System.out.println("S構造方法"); } }// 測試public class Demo public static void main(String[] args){ // 創建子類對象 new S(); } }// 結果F靜態代碼塊 S靜態代碼塊 F普通代碼塊 F構造方法 S普通代碼塊 S構造方法
程序進入JVM
中的方法區,子類繼承父類,父類進行加載實例信息進入到開闢的內存中,然後執行完再執行構造方法,在堆內存中new
一個對象,new S();
在子類的構造方法中會有默認的super()
,加載父類,如果子類調用默認調用super()
,而父類沒有無參的構造方法,而是有參的構造方法,那麼就要自己添加,在super(xxx)
中。