日本搞逼视频_黄色一级片免费在线观看_色99久久_性明星video另类hd_欧美77_综合在线视频

國內(nèi)最全I(xiàn)T社區(qū)平臺(tái) 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2
您當(dāng)前位置:首頁 > 互聯(lián)網(wǎng) > Java反射機(jī)制(四)―番外篇,實(shí)例化方法深入

Java反射機(jī)制(四)―番外篇,實(shí)例化方法深入

來源:程序員人生   發(fā)布時(shí)間:2014-10-11 08:00:00 閱讀次數(shù):3084次
    反射機(jī)制這幾篇博客寫下來發(fā)現(xiàn)涉及到Java類的加載機(jī)制,這部分的內(nèi)容也比較獨(dú)立的一部分,因此單另一篇來寫。在JAVA中任何的類都是需要加載到JVM中才能運(yùn)行的。之前Class Loader介紹了類的加載機(jī)制,那么這里要說的是不同加載方式之間的對比,好能對JAVA類的實(shí)例化過程有更深刻的體會(huì)。  

new和Class.newInstance

    我們說代碼里出現(xiàn)new關(guān)鍵字意味著對于可能變動(dòng)的代碼,耦合過高了。遇到這種情況我們會(huì)用反射機(jī)制來去除new關(guān)鍵字,這在代理模式里我們見過了。實(shí)際上也就是用了Class.newInstance來代替。這說明這兩種方式都可以得到相同的對象實(shí)例,但是它們之間存在區(qū)別,耦合度不同。
    實(shí)際上在理解上我們可以認(rèn)為,Class.newInstanc方式來實(shí)例化對象是對new關(guān)鍵字的拆分成兩步了。因?yàn)椋珻lass.newInstance的使用是有前提的,要保證類已經(jīng)加載到JVM中,并且已經(jīng)鏈接。看如下代碼:
<span style="font-family:FangSong_GB2312;font-size:18px;"><span style="font-family:FangSong_GB2312;">public static void main(String[] arg) throws ClassNotFoundException, InstantiationException, IllegalAccessException{ //從當(dāng)前線程取得正在運(yùn)行的加載器 ClassLoader cl=Thread.currentThread().getContextClassLoader(); cl.loadClass("com.zjj.ClassTest.Test"); //加載測試類到JVM Class c2=cl.getClass(); //得到類的Class對象 c2.newInstance(); //實(shí)例化對象 } }</span></span>
    這里不用Class.forName來得到Class對象是為了保證類被加載了但是沒有被鏈接。 這段代碼看著貌似沒什么錯(cuò),編譯也沒有問題,但是運(yùn)行的時(shí)候就出錯(cuò)了。也就是說通過如上方法加載的類是沒有被鏈接的,因此newInstance方法無法執(zhí)行。
    前面說理解上可以簡單的認(rèn)為是通過Class.Instance方式是new拆分的兩步,但是事實(shí)上new要比Class.Instance做的多。Class.Instance方法只能訪問無參數(shù)的構(gòu)造函數(shù),new則都可以訪問。建立一個(gè)有兩個(gè)構(gòu)造函數(shù)的測試類,看客戶端調(diào)用代碼:
<span style="font-family:FangSong_GB2312;font-size:18px;"><span style="font-family:FangSong_GB2312;">public static void main(String[] arg) throws ClassNotFoundException, InstantiationException, IllegalAccessException{ Class c=Class.forName("com.zjj.ClassTest.Test"); c.newInstance(); new Test("ni"); } }</span></span>
    輸出結(jié)果為:
        無參數(shù)的構(gòu)造函數(shù)
        帶參數(shù)的構(gòu)造函數(shù)
    如果在newInstance中傳入?yún)?shù)去調(diào)用帶參數(shù)的構(gòu)造函數(shù)的話是會(huì)報(bào)錯(cuò)的,無法通過編譯。相對來說newInstance是弱類型,new是強(qiáng)類型。

Class.forName和classLoad.loadClass

    講這兩個(gè)的區(qū)別之前我們先要了解,JVM會(huì)執(zhí)行靜態(tài)代碼段,要記住一個(gè)概念,靜態(tài)代碼是和class綁定的,class裝載成功就表示執(zhí)行了靜態(tài)代碼了,以后也就不會(huì)再走這段靜態(tài)代碼了。 也就是說靜態(tài)代碼段是只會(huì)執(zhí)行一次的,在類被加載的時(shí)候。另外我們還需要知道,類的加載過程分為裝載、連接、初始化。還有就是,JVM遇到類請求時(shí)它會(huì)先檢查內(nèi)存中是否存在,如果不存在則去加載,存在則返回已存在的Class對象。
    那么這兩個(gè)方法的區(qū)別就在于執(zhí)行的這三個(gè)過程不一樣。forName有兩個(gè)函數(shù)(多態(tài)),三個(gè)參數(shù)時(shí)forName(String className, boolean initialize, ClassLoader loader)第二個(gè)參數(shù)為True時(shí)則類會(huì)鏈接,會(huì)初始化。為False時(shí),如果原來不存在則一定不會(huì)連接和初始化,如果原來存在被連接的Class對象,則返回該對象但是依然不會(huì)初始化。單參數(shù)時(shí),默認(rèn)initialize是為True的。
    loadClass也是多態(tài)loadClass(String name)單參數(shù)時(shí), resolve=false。如果該類已經(jīng)被該類裝載器所裝載,那么,返回這個(gè)已經(jīng)被裝載的類型的Class的實(shí)例,否則,就用這個(gè)自定義的類裝載器來裝載這個(gè)class,這時(shí)不知道是否被連接。絕對不會(huì)被初始化!這時(shí)唯一可以保證的是,這個(gè)類被裝載了。但是不知道這個(gè)類是不是被連接和初始化了。
    loadClass(String name, boolean resolve)resolve=true時(shí),則保證已經(jīng)裝載,而且已經(jīng)連接了。 resolve=falses時(shí),則僅僅是去裝載這個(gè)類,不關(guān)心是否連接了,所以此時(shí)可能被連接了,也可能沒有被連接。下面通過測試來驗(yàn)證以上說的內(nèi)容,代碼如下:
    Test類:
<span style="font-family:FangSong_GB2312;font-size:18px;"><span style="font-family:FangSong_GB2312;">public class Test { static { System.out.println("靜態(tài)初始化"); } public Test(){ System.out.println("無參數(shù)的構(gòu)造函數(shù)"); } public Test(String str){ System.out.println("帶參數(shù)的構(gòu)造函數(shù)"); } { System.out.println("非靜態(tài)初始化"); } }</span></span>
    測試一:客戶端調(diào)用代碼
<span style="font-family:FangSong_GB2312;font-size:18px;"><span style="font-family:FangSong_GB2312;">public static void main(String[] arg) throws ClassNotFoundException, InstantiationException, IllegalAccessException{ Class c=Class.forName("com.zjj.ClassTest.Test"); } }</span></span>
    輸出結(jié)果為:靜態(tài)初始化
    說明:Class.forName時(shí)類執(zhí)行了裝載、連接、初始化三個(gè)步驟。
    測試二:客戶端代碼改為
<span style="font-family:FangSong_GB2312;font-size:18px;"><span style="font-family:FangSong_GB2312;">public static void main(String[] arg) throws ClassNotFoundException, InstantiationException, IllegalAccessException{ ClassLoader cl=Thread.currentThread().getContextClassLoader(); Class c=Class.forName("com.zjj.ClassTest.Test", false, cl); } }</span></span>
    輸出結(jié)果為:initialize=true時(shí)輸出,靜態(tài)初始化。為false時(shí)沒有輸出
    說明:為true時(shí)類執(zhí)行了裝載、連接、初始化三個(gè)步驟。為false時(shí)沒有初始化,為知是不是連接。
    測試三:客戶端代碼改為
<span style="font-family:FangSong_GB2312;font-size:18px;"><span style="font-family:FangSong_GB2312;">public static void main(String[] arg) throws ClassNotFoundException, InstantiationException, IllegalAccessException{ ClassLoader cl=Thread.currentThread().getContextClassLoader(); Class c=Class.forName("com.zjj.ClassTest.Test", false, cl); c.newInstance(); } }</span></span>
    輸出結(jié)果為:
        靜態(tài)初始化
        非靜態(tài)初始化
        無參數(shù)的構(gòu)造函數(shù)
    說明:為了保證JVM中不存在之前加載過的類,特地清理了JVM內(nèi)存。但是輸出結(jié)果不變,說明為false時(shí)執(zhí)行了裝載和鏈接,否則newInstance是無法執(zhí)行的(前面說過了newInstance的執(zhí)行條件)。但是資料說可能還存在不連接的情況!!有待考證。
    測試四:客戶端代碼改為
<span style="font-family:FangSong_GB2312;font-size:18px;"><span style="font-family:FangSong_GB2312;">public static void main(String[] arg) throws ClassNotFoundException, InstantiationException, IllegalAccessException{ Class c=Class.forName("com.zjj.ClassTest.Test"); ClassLoader cl=Thread.currentThread().getContextClassLoader(); Class c=Class.forName("com.zjj.ClassTest.Test", true, cl); } }</span></span>
    輸出結(jié)果為:靜態(tài)初始化
    說明:如果原來存在加載過的類,那么第二次執(zhí)行加載請求時(shí)返回存在的。因?yàn)椋o態(tài)初始化只執(zhí)行了一次。
    測試五:客戶端代碼改為
<span style="font-family:FangSong_GB2312;font-size:18px;"><span style="font-family:FangSong_GB2312;">public static void main(String[] arg) throws ClassNotFoundException, InstantiationException, IllegalAccessException{ //從當(dāng)前線程取得正在運(yùn)行的加載器 ClassLoader cl=Thread.currentThread().getContextClassLoader(); cl.loadClass("com.zjj.ClassTest.Test"); //加載測試類到JVM Class c2=cl.loadClass("com.zjj.ClassTest.Test").getClass(); //得到類的Class對象 c2.newInstance(); //實(shí)例化對象 } }</span></span>
    輸出結(jié)果:報(bào)錯(cuò)
    說明:此時(shí)loadClass方法加載到內(nèi)存中的類是未連接的,當(dāng)然不會(huì)初始化。因此也就沒有“靜態(tài)初始化”的輸出。
    測試六:不知道為什么沒有發(fā)現(xiàn)代碼中的ClassLoader存在兩個(gè)參數(shù)的loadClass方法。
    總結(jié):至此方法對比結(jié)束,這篇博客主要是更細(xì)致的了解了JVM加載類的過程和不同方式之間的區(qū)別。其實(shí)際上只是封裝的程度不一樣,也就是方法的粒度的差別。當(dāng)然,有一點(diǎn)內(nèi)容還沒有通過自己的測試得到驗(yàn)證,可能是我的方法不對或者是資料有問題。權(quán)且記下這個(gè)問題!下篇博客再見!




         
生活不易,碼農(nóng)辛苦
如果您覺得本網(wǎng)站對您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關(guān)閉
程序員人生
主站蜘蛛池模板: 免费一级黄色 | 国产精品成人自拍 | 日韩av网站大全 | 日韩视频久久 | 毛片免费观看视频 | 国产4区 | 黄色a视频在线观看 | 国产专区在线 | 97总资源 | 亚洲成人av一区二区 | 一区二区三区四区在线视频 | 成人黄色av网站 | 亚洲另类xxxx | 久久九九99 | 中文字幕免费播放 | 91欧美精品成人综合在线观看 | 国内久久精品 | 亚洲视频自拍 | 在线激情网站 | 亚洲精品成人在线 | 亚洲精品一区在线 | 一区二区日韩精品 | 午夜视频一区 | 亚洲视频在线视频 | 国产在线精品91国自产拍免费 | 亚洲欧美激情精品一区二区 | 免费观看一区二区 | 亚洲色图欧美激情 | 亚洲第八页 | 国产福利精品视频 | 成人福利在线播放 | 韩国一级片在线播放 | 中文一区二区视频 | 美女二区 | 精品三级在线观看 | 日韩欧美一区二区在线视频 | 最新国产精品 | 日本一区久久 | 国产在线一区二区三区视频 | 精品国产1区2区 | av片网站|