多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > 互聯網 > Java反射機制(四)―番外篇,實例化方法深入

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

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

new和Class.newInstance

    我們說代碼里出現new關鍵字意味著對于可能變動的代碼,耦合過高了。遇到這種情況我們會用反射機制來去除new關鍵字,這在代理模式里我們見過了。實際上也就是用了Class.newInstance來代替。這說明這兩種方式都可以得到相同的對象實例,但是它們之間存在區別,耦合度不同。
    實際上在理解上我們可以認為,Class.newInstanc方式來實例化對象是對new關鍵字的拆分成兩步了。因為,Class.newInstance的使用是有前提的,要保證類已經加載到JVM中,并且已經鏈接。看如下代碼:
<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(); cl.loadClass("com.zjj.ClassTest.Test"); //加載測試類到JVM Class c2=cl.getClass(); //得到類的Class對象 c2.newInstance(); //實例化對象 } }</span></span>
    這里不用Class.forName來得到Class對象是為了保證類被加載了但是沒有被鏈接。 這段代碼看著貌似沒什么錯,編譯也沒有問題,但是運行的時候就出錯了。也就是說通過如上方法加載的類是沒有被鏈接的,因此newInstance方法無法執行。
    前面說理解上可以簡單的認為是通過Class.Instance方式是new拆分的兩步,但是事實上new要比Class.Instance做的多。Class.Instance方法只能訪問無參數的構造函數,new則都可以訪問。建立一個有兩個構造函數的測試類,看客戶端調用代碼:
<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>
    輸出結果為:
        無參數的構造函數
        帶參數的構造函數
    如果在newInstance中傳入參數去調用帶參數的構造函數的話是會報錯的,無法通過編譯。相對來說newInstance是弱類型,new是強類型。

Class.forName和classLoad.loadClass

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




         
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 欧美另类xxxx | 福利在线国产 | 亚洲综合视频在线 | 亚洲视频成人 | 国产精品 第二页 | 嘿咻视频免费网站 | 亚洲精品久久久久久久久久久网站 | 免费乱码中文字幕网站 | 欧美精品区 | 亚洲一区二区三区深夜天堂 | 亚洲最大的黄色网 | 免费h视频在线观看 | 日韩最新视频一区二区三 | 美国免费毛片 | 国产精品久久久久影视不卡 | 最近手机中文字幕高清1 | 国产成人做受免费视频 | 伊人久久99亚洲精品久久频 | 午夜影院官网 | 欧美永久免费 | 国产精品99久久久久久人 | 99一级毛片 | 欧美jizz18性欧美年轻 | bt 自拍 另类 综合 欧美 | 网红毛片| 91精品国产亚洲爽啪在线影院 | 2020中文字幕 | 一区二区三区国产 | 欧美一级www | 精品无码中出一区二区 | 自拍视频啪| 亚洲一区二区色 | 欧美成人亚洲国产精品 | freexxxhd性欧美 | 美日韩精品 | 看黄色网址 | 日韩免费高清一级毛片在线 | 最近手机中文字幕高清1 | 中文字幕一区二区三区永久 | 国产精品秋霞午夜 | 免费一级大毛片a一观看不卡 |