哪吒2之魔童闹海|哪吒2之魔童归来免费观看|哪吒2在线观看|哪吒2魔童闹海电影免费观看|哪吒2免费观看完整版大电影|哪吒1免费观看完整版

新疆軟件開發(fā)

本站首頁 軟件開發(fā) 成功案例 公司新聞 公司簡介 客服中心 軟件技術(shù) 網(wǎng)站建設(shè)
  您現(xiàn)在的位置: 新疆二域軟件開發(fā)公司 >> Java技術(shù) >> 文章正文

JAVA程序類加載及其反射機(jī)制

JAVA中類文件加載是動態(tài)的。JVM指令是被封裝在了. class文件里面,而.class文件的加載過程是動態(tài)的,也就是說當(dāng)我們用到的時(shí)候才會去加載,如果不用的話,就不會去加載我們的類。這里所說的用到包括兩種方式,第一種就是new一個(gè)對象的時(shí)候(這個(gè)時(shí)候要特別注意,當(dāng)設(shè)計(jì)到多態(tài)的時(shí)候,就會有一點(diǎn)點(diǎn)變化,這時(shí)候編譯器會做一些優(yōu)化,這樣以來當(dāng)加載的時(shí)候會提前加載設(shè)計(jì)到多態(tài)的類,關(guān)于這一點(diǎn)下面有個(gè)例子(example 1)來說明。另一種就是當(dāng)一個(gè)類的靜態(tài)代碼被調(diào)用的時(shí)候。

java 代碼//example 1 // Zoo.java abstract class Animal { Animal(){ System.out.println("Animal constructor"); } } class Tiger extends Animal { Tiger(){ System.out.println("Tig constructor "); } } class Dog extends Animal { Dog(){ System.out.println("Dog Constructor "); } } public class Zoo { private Animal am; //Example 1.1 //private Dog am; Example 1.2 private Tiger tiger; Zoo(){ tiger = new Tiger(); am = new Dog(); } public static void main(String [] args){ System.out.println("new Zoo before"); Zoo z = new Zoo(); System.out.println("new Zoo after "); } }

  當(dāng)我們注釋掉Example.1.1行時(shí),運(yùn)行Example1.2行,結(jié)果如下:

  Example 1.2

  分析以上兩圖的運(yùn)行結(jié)果我們可以看出:當(dāng)我們將子類對象賦值給父類時(shí),編譯器會做一點(diǎn)優(yōu)化,于是加載器在還沒有new 子類對象的時(shí)候已經(jīng)加載了父類以及子類(example1.1結(jié)果),當(dāng)不存在多態(tài)的時(shí)候,我們可以看到是當(dāng)要new Dog()的時(shí)候才會加載Dog以及父類。無論何種方式,在new之前,類確實(shí)已經(jīng)加載到了內(nèi)存中。

  JAVA為我們提供了兩種動態(tài)機(jī)制。第一種是隱式機(jī)制。其實(shí)new一個(gè)對象和調(diào)用類的靜態(tài)方法時(shí),就是隱式機(jī)制在工作。第二種是顯示機(jī)制。顯示的機(jī)制又有兩種策略(第一種是用java.lang.Class的forName(String str)方法,第二種是用java.lang.ClassLoader的loadClass())。

  第一種:利用forName方法

  當(dāng)我們查API文檔就會發(fā)現(xiàn)forName方法有兩種形式。分別如下:
public static Class<?> forName(String className) throws ClassNotFoundException public static Class<?> forName(String name, boolean initialize, ClassLoader loader) throws ClassNotFoundException

  先來說說第二種方法:第二個(gè)方法值得注意的就是第二個(gè)參數(shù)boolean initialize,如果我們把這個(gè)參數(shù)設(shè)置為false,那么當(dāng)我們加載完類后就不會執(zhí)行靜態(tài)代碼和靜態(tài)的初始化動作。只有當(dāng)我們new一個(gè)對象的時(shí)候才會初始化。而第三個(gè)參數(shù)是用來指明類的加載器的。

  如果查看java.lang.Class類的源代碼,上述兩種方法最終都會調(diào)用Class類中的私有的native方法forName0(),此方法的聲明如下:

private static native Class forName0(String name, boolean init , ClassLoader loader) throws ClassNotFoundException;

  所以當(dāng)我們調(diào)用Class.forName(name )時(shí),其實(shí)是在方法內(nèi)部調(diào)用了:
forName0(name, true, ClassLoader.getCallerClassLoader());

  當(dāng)我們調(diào)用Class.forName(name, initialize, loader )的時(shí)候,實(shí)際上此方法內(nèi)部調(diào)用了:
forName0(name, initialize, loader);

  下面看一個(gè)例子,如果方法中第二個(gè)參數(shù)為false的情況:

java 代碼//example 2.1 // Zoo.java abstract class Animal { static { System.out.println("Animal static code block "); } Animal(){ System.out.println("Animal constructor"); } } class Tiger extends Animal { Tiger(){ System.out.println("Tig constructor "); } } class Dog extends Animal { Dog(){ System.out.println("Dog Constructor "); } } public class Zoo { public static void main(String [] args)throws Exception { System.out.println("new Zoo before"); Zoo z = new Zoo(); Class c = Class.forName("Dog",false,z.getClass().getClassLoader()); System.out.println("initilize before "); Animal dog = (Animal)c.newInstance(); System.out.println("new Zoo after "); } }

  類加載完成后并沒有立即執(zhí)行靜態(tài)初始化代碼,而是到了實(shí)例化的時(shí)候才進(jìn)行了靜態(tài)初始化。有時(shí)候我們會說靜態(tài)代碼是在類第一次被加載時(shí)執(zhí)行的,并且只執(zhí)行一次。其實(shí)這是對與new一個(gè)對象,第一次訪問類的靜態(tài)代碼以及第二個(gè)參數(shù)為true時(shí)而言的,對于動態(tài)的加載來說,如果forName方法的第二個(gè)參數(shù)設(shè)置為false,那么就是在實(shí)例化的時(shí)候才會執(zhí)行靜態(tài)初始化。當(dāng)然默認(rèn)情況下第二個(gè)參數(shù)是true.

  第二種方法:利用Class對象獲取的ClassLoader裝載。

  下面是一個(gè)簡單的例子:

java 代碼//Example 2.2 //Zoo.java abstract class Animal { static { System.out.println("Animal static code block "); } Animal(){ System.out.println("Animal constructor"); } } class Tiger extends Animal { Tiger(){ System.out.println("Tig constructor "); } } class Dog extends Animal { Dog(){ System.out.println("Dog Constructor "); } } public class Zoo { public static void main(String [] args)throws Exception { Class c = Zoo.class; ClassLoader loader = c.getClassLoader(); System.out.println("loader before"); Class dog = loader.loadClass("Dog"); System.out.println("instance before "); Animal an = (Animal)dog.newInstance(); } }

  loader完成以后并沒有立即進(jìn)行靜態(tài)代碼的執(zhí)行。只有當(dāng)newInstance()的時(shí)候才執(zhí)行靜態(tài)初始化,這和把public static Class forName(String name, boolean initialize, ClassLoader loader)的第二個(gè)參數(shù)指定為false的情況完全一樣。其實(shí)每當(dāng)我們寫完一個(gè)編譯單元以后就會得到一個(gè).calss文件,這個(gè)文件中就包含了該類的Class對象。JVM就是利用這個(gè)class對象來進(jìn)行動態(tài)裝載類的。

作者:佚名 | 文章來源:賽迪網(wǎng) | 更新時(shí)間:2007-10-22 10:10:32

  • 上一篇文章:

  • 下一篇文章:

  • 相關(guān)文章:
    JAVA開發(fā)的6個(gè)實(shí)踐的例子
    JAVA中的抽象類型的一些概念
    java語言開發(fā)程序中的幾個(gè)例子大家看看
    了解java開發(fā)語言在軟件開發(fā)中的幾個(gè)誤區(qū)
    如何才能使用Java實(shí)現(xiàn)內(nèi)部領(lǐng)域的特定語言
    Java開發(fā)學(xué)習(xí)小心使用Date以及Time類
    sun最近修補(bǔ)了一部分java的安全補(bǔ)丁
    Java程序員應(yīng)該了解那些開源協(xié)議
    java性能優(yōu)化的一些見解
    解析c#語言和java語言最相似的地方
    軟件技術(shù)
    · 開發(fā)語言
    · Java技術(shù)
    · .Net技術(shù)
    · 數(shù)據(jù)庫開發(fā)
    最新文章  
    ·j2se 嵌入式腳本抓取引擎
    ·JAVA開發(fā)的6個(gè)實(shí)踐的例子
    ·JBuilder7 / Weblogic7開發(fā)
    ·JAVA中的抽象類型的一些概
    ·java語言開發(fā)程序中的幾個(gè)
    ·了解java開發(fā)語言在軟件開
    ·如何才能使用Java實(shí)現(xiàn)內(nèi)部
    ·Java開發(fā)學(xué)習(xí)小心使用Date
    ·Java程序員應(yīng)該了解那些開
    ·java性能優(yōu)化的一些見解
    ·介紹JDK5.0一些collection
    ·基礎(chǔ)學(xué)習(xí):java中使用存儲
    ·解析c#語言和java語言最相
    ·Java語言學(xué)習(xí):jAVA中 的多
    ·Java是不是應(yīng)該增加新特性
    關(guān)于我們 | 軟件開發(fā) | 下載試用 | 客服中心 | 聯(lián)系我們 | 友情鏈接 | 網(wǎng)站地圖 | 新疆電子地圖 | RSS訂閱
    版權(quán)所有 © 2016 新疆二域軟件開發(fā)網(wǎng) www.pg11qqq.com All Rights Reserved 新ICP備14003571號
    新疆軟件開發(fā)總機(jī):0991-4842803、4811639.
    客服QQ:596589785 ;地址:新疆烏魯木齊北京中路華聯(lián)大廈A-5C 郵編:830000