作者:nnngu
GitHub:https://github.com/nnngu
博客園:http://www.cnblogs.com/nnngu
簡(jiǎn)書(shū):http://www.reibang.com/users/1df20d76ea5c
知乎:https://www.zhihu.com/people/nnngu/posts
Class.forName() 與 ClassLoader.loadClass() 大家都知道是反射用來(lái)構(gòu)造類的方法亮隙,但是他們的用法還是有一定區(qū)別的穷蛹。
在講區(qū)別之前,我覺(jué)得很有必要把類的加載過(guò)程在此整理一下。
在Java中,類加載器把一個(gè)類加載進(jìn)Java虛擬機(jī)中,要經(jīng)過(guò)三個(gè)步驟來(lái)完成:加載、鏈接和初始化动分,其中鏈接又可以分成驗(yàn)證、準(zhǔn)備和解析三步红选,除了解析外澜公,其它步驟是嚴(yán)格按照順序完成的,各個(gè)步驟的主要工作如下:
加載:查找和導(dǎo)入類或接口的二進(jìn)制數(shù)據(jù)喇肋;
-
鏈接:執(zhí)行下面的校驗(yàn)坟乾、準(zhǔn)備和解析步驟,其中解析步驟是可以選擇的蝶防;
驗(yàn)證:檢查導(dǎo)入類或接口的二進(jìn)制數(shù)據(jù)的正確性甚侣;
準(zhǔn)備:給類的靜態(tài)變量分配并初始化存儲(chǔ)空間;
解析:將符號(hào)引用轉(zhuǎn)成直接引用间学;
初始化:激活類的靜態(tài)變量的初始化Java代碼和靜態(tài)Java代碼塊殷费。

于是乎我們可以開(kāi)始看2者的區(qū)別了印荔。
Class.forName(className) 方法,其實(shí)調(diào)用的方法是Class.forName(className,true,classloader); 注意看第2個(gè)boolean參數(shù)宗兼,它表示的意思,在加載之后必須初始化氮采。在執(zhí)行過(guò)此方法后殷绍,目標(biāo)對(duì)象的靜態(tài)塊代碼已經(jīng)被執(zhí)行,靜態(tài)參數(shù)也已經(jīng)被初始化鹊漠。
再看ClassLoader.loadClass(className) 方法主到,其實(shí)他調(diào)用的方法是ClassLoader.loadClass(className,false); 注意看第2個(gè) boolean 參數(shù),該參數(shù)表示目標(biāo)對(duì)象被加載后不進(jìn)行鏈接躯概,這就意味著不會(huì)去執(zhí)行該類靜態(tài)塊中的內(nèi)容登钥。因此兩者的區(qū)別就顯而易見(jiàn)了。