在java中,一個(gè)類被使用要經(jīng)過裝載,連接,初始化這樣的過程
一、裝載:
類裝載器(Bootstrap ClassLoader 或者用戶自定義的ClassLoader) 把編譯形成的class文件載入內(nèi)存,創(chuàng)建類相關(guān)的Class對(duì)象,這個(gè)Class對(duì)象封裝了我們要使用的類的類型信息。
二、連接
?連接階段又可以分為三個(gè)子步驟:驗(yàn)證、準(zhǔn)備和解析。
(1)驗(yàn)證就是要確保java類型數(shù)據(jù)格式 的正確性,并適于JVM使用
(2)準(zhǔn)備階段,JVM為靜態(tài)變量分配內(nèi)存空間,并設(shè)置默認(rèn)值,注意,這里是設(shè)置默認(rèn)值,比如說int型的變量會(huì)被賦予默認(rèn)值0 。在這個(gè)階段,JVM可能還會(huì)為一些數(shù)據(jù)結(jié)構(gòu)分配內(nèi)存,目的 是提高運(yùn)行程序的性能,比如說方法表
(3)解析過程就是在類型的常量池中尋找類、接口、字段和方法的符號(hào)引用,把這些符號(hào)引用替換成直接引用。這個(gè)階段可以被推遲到初始化之后,當(dāng)程序運(yùn)行的過程中真正使用某個(gè)符號(hào)引用的時(shí)候 再去解析它
三、初始化
類會(huì)在首次被“主動(dòng)使用”時(shí)執(zhí)行初始化,為類(靜態(tài))變量賦予正確的初始值。在Java代碼中,一個(gè)正確的初始值是通過類變量初始化語句或者靜態(tài)初始化塊給出的。而我們這里所說的主動(dòng)使用 包括: ?創(chuàng)建類的實(shí)例、調(diào)用類的靜態(tài)方法、使用類的非常量靜態(tài)字段、調(diào)用JavaAPI中的某些反射方法、 初始化某個(gè)類的子類、 含有main()方法的類啟動(dòng)時(shí)
初始化一個(gè)類包括兩個(gè)步驟:
(1) ?如果類存在直接父類的話,且直接父類還沒有被初始化,則先初始化其直接父類
(2) ?如果類存在一個(gè)初始化方法,就執(zhí)行此方法注:初始化接口并不需要初始化它的父接口。
以上就是java中的類初始化
我所見到的調(diào)用順序:
main函數(shù),調(diào)用類A,A繼承Abase
1、main函數(shù)所在類的靜態(tài)代碼塊或者靜態(tài)成員的初始化
2、main函數(shù)調(diào)用
3、main中用到類A的基類Abase中,靜態(tài)代碼塊或者靜態(tài)成員的初始化
4、類A的靜態(tài)代碼塊或者靜態(tài)成員的初始化 (<cinit>函數(shù))
5、Abase的構(gòu)造函數(shù)調(diào)用
6、A的構(gòu)造函數(shù)調(diào)用,此時(shí)實(shí)際上在class文件中會(huì)把類中的非靜態(tài)成員變量和非靜態(tài)代碼塊加入到已有的構(gòu)造函數(shù)代碼之前,形成一個(gè)最終的構(gòu)造函數(shù),非靜態(tài)成員變量和非靜態(tài)代碼塊的執(zhí)行順序跟代碼的書寫順序一致 !<init>
比如
```
class A{
int a = 0;//1
{
a = 1;//2
}
public A(){
a = 2;//3
}
}
```
那么構(gòu)造類A的時(shí)候調(diào)用順序是1-2-3
也就是說要注意此時(shí)成員變量的初始化都是在調(diào)用構(gòu)造函數(shù)所在的線程中執(zhí)行的!
7、最后是使用到的方法調(diào)用
參考鏈接:http://blog.csdn.net/moreevan/article/details/6968718
http://www.cnblogs.com/zlingh/p/4040567.html