結論:
參考https://blog.csdn.net/qq_43672627/article/details/86616624
類的初始化:是完成程序執行前的准備工作。在這個階段,靜態的(變量,方法,代碼塊)會被執行。同時在會開辟一塊存儲空間用來存放靜態的數據。初始化只在類加載的時候執行一次。
類的實例化:是指創建一個對象的過程。這個過程中會在堆中開辟內存,將一些非靜態的方法,變量存放在里面。在程序執行的過程中,可以創建多個對象,既多次實例化。每次實例化都會開辟一塊新的內存。
1.主要區別
2.基礎知識
2.1java類的生命周期:
指一個class文件從加載到卸載的全過程,類的完整生命周期包括7個部分:加載——驗證——准備——解析——初始化——使用——卸載,如下圖所示
其中,驗證——准備——解析 稱為連接階段,除了解析外,其他階段是順序發生的,而解析可以與這些階段交叉進行,因為Java支持動態綁定(晚期綁定),需要運行時才能確定具體類型;在使用階段實例化對象
2.2類加載過程:
加載:通過類名獲取類的二進制字節流是通過類加載器來完成的。其加載過程使用“雙親委派模型”
驗證:當一個類被加載之后,必須要驗證一下這個類是否合法,比如這個類是不是符合字節碼的格式、變量與方法是不是有重復、數據類型是不是有效、繼承與實現是否合乎標准等等。總之,這個階段的目的就是保證加載的類是能夠被jvm所運行。
准備:為類變量(靜態變量)在方法區分配內存,並設置零值。注意:這里是類變量,不是實例變量,實例變量是對象分配到堆內存時根據運行時動態生成的。
解析:把常量池中的符號引用解析為直接引用:根據符號引用所作的描述,在內存中找到符合描述的目標並把目標指針指針返回。
初始化:類的初始化過程是這樣的:按照順序自上而下運行類中的變量賦值語句和靜態語句,如果有父類,則首先按照順序運行父類中的變量賦值語句和靜態語句在類的初始化階段,只會初始化與類相關的靜態賦值語句和靜態語句,也就是有static關鍵字修飾的信息,而沒有static修飾的賦值語句和執行語句在實例化對象的時候才會運行。執行<clinit>()方法(clinit是class initialize的簡寫)
實例化:在堆區分配內存空間,執行實例對象初始化,設置引用變量a指向剛分配的內存地址
2.3 運行時區內存分配
3.具體流程
類A
public class A { private int m=2; private String str1="youyou"; public final static String MESS="world"; static String ms="world"; public String getName(String input){ String temp=input; return temp; } public static int getId(){return 0;} }
Test類
public class Test { public static void main(String[] args) { Class clazz=A.class; A a=new A(); A a1=new A(); } public void change(int i) { i=123; } }
以上面來舉例
引用對象:A中成員B b,b即為引用對象,
常量三種:8種基本數據類型byte boolean,char short,float int,dobule long的具體的值,
受final修改的變量
“”雙引號引起來的字符串
附:
java內存分配圖解:https://blog.csdn.net/shunfa888/article/details/79765031
類成員變量和局部變量內存分配:https://www.cnblogs.com/chuanqi1995/p/11644334.html
類的加載過程詳解:https://blog.csdn.net/yanliguoyifang/article/details/80964237