詳細介紹類加載與反射
Java中,反射是一種強大的工具。它使您能夠創(chuàng)建靈活的代碼,這些代碼可以在運行時裝配,無需在組件之間進行源代表鏈接。下面介紹類加載和反射,供參考。
一、類加載
當調(diào)用java命令運行某個Java程序時,該命令將啟動一條Java虛擬機進程,同一個JVM的所有線程,所有變量都處于同一進程里,它們都是用該JVM進程的內(nèi)存區(qū)
- 程序運行到***正常結(jié)束
- 程序運行到使用System.exit()或Runtime().exit()代碼結(jié)束程序
- 程序執(zhí)行過程中遇到未捕獲的異?;蝈e誤而結(jié)束
- 程序所在平臺強制結(jié)束了JVM進程
類的加載
類加載指的是將類的class文件讀入內(nèi)存,并為之創(chuàng)建一個java.lang.Class對象,而系統(tǒng)中所有的類,它們實際上也是對象,稱為類對象,它們都是java.lang.Class的實例,虛擬機為每種類型管理一個***的Class對象,也就是說,每個類(型)都有一個Class對象.
類的連接
連接階段將會負責將類的二進制數(shù)據(jù)合并到JRE中
- 驗證
- 準備:類準備階段則負責將類的靜態(tài)屬性分配內(nèi)存,并設(shè)置默認初始值
- 解析
類的初始化
在類的初始化階段,虛擬機負責對類進行初始化,主要就是對靜態(tài)屬性進行初始化,在Java類中對靜態(tài)屬性指定初始值有兩種方式:
(1)聲明靜態(tài)屬性時指定初始值;
(2)使用靜態(tài)初始化塊為靜態(tài)屬性制定初始值
1、當Java程序***通過下面6種方式來使用某個類或接口時,系統(tǒng)就會初始化該類或接口
a) 創(chuàng)建類的實例
b) 調(diào)用某個類的靜態(tài)方法
c) 訪問某個類或接口的靜態(tài)屬性,或為該靜態(tài)屬性賦值
d) 使用反射方式來強制創(chuàng)建某個類或接口對應(yīng)的java.lang.Class對象
e) 初始化某個類的子類,當初始化某個類的子類時,該子類的所有父類都會被初始化
f) 直接使用java.exe命令來運行某個主類時,程序會先初始化該主類
2、類加載器
類加載器負責將.class文件加載到內(nèi)存中,并為之生成對應(yīng)的java.lang.Class對象
在Java中,一個類用其全限定類名(包括包名和類名)作為標識
在JVM中,一個類用其全限定類名和其類加載器作為其唯一標識
當JVM啟動時,會形成由三個類加載器組成的:
Bootstrap ClassLoader:根類加載器 它不是java.lang.ClassLoader的子類,而是由JVM自身實現(xiàn)rt.jar
Extension ClassLoader:擴展類加載器 它負責加載JRE的擴展目錄ext中JAR的類包
System ClassLoader:系統(tǒng)類加載器 它負責在JVM啟動時,加載來自命令java中的-classpath選項或java.class.path系統(tǒng)屬性,或CLASSPATH環(huán)境變量所指定的JAR包和類路徑,默認是以當前路徑作為系統(tǒng)加載路徑
AppClassLoader
用戶自定義類加載器
3、JVM類加載機制
全盤負責
父類委托:所謂父類委托是先讓parent(父)類加載器試圖加載該Class,只有在父類加載器無法加載該類時才嘗試從自己的類路徑中加載該類
緩存機制
4、通過反射查看類信息
Java程序中獲得Class對象通常有如下三種方法:
a) 使用Class類的forName()靜態(tài)方法.該方法需要傳入字符串參數(shù),該字符串參數(shù)的值是某個類的全限定類名(必須添加完整包名)
b) 調(diào)用某個類的class屬性來獲取該類對應(yīng)的Class對象.
c) 調(diào)用某個對象的getClass()方法,該方法是java.lang.Object類中的一個方法,所以所有java對象都可以調(diào)用該方法,該方法將會返回該對象所屬類對應(yīng)的Class對象
b方法:代碼更安全,程序在編譯階段就可以檢查需要訪問的Class對象是否存在
程序性能提高,因為這種方法無需調(diào)用方法,所以性能更好
一旦獲得某個類所對應(yīng)的Class對象后,就可以調(diào)用Class對象的方法來獲得該對象和該類的真實信息
getDeclared 與訪問級別無關(guān),顯式聲明的
get 獲得所有的但只是public,包括繼承的
5、使用反射生成并操作對象
Class對象可以獲得該類里包括的方法(由Methode對象表示),構(gòu)造器(由Constructor對象表示),Field(Field對象表示),這三個類都定義在java.lang.reflect包下,并實現(xiàn)了java.lang.reflect.Member接口,程序可以通過Method對象來執(zhí)行對應(yīng)的方法,通過Constructor對象來調(diào)用對應(yīng)的構(gòu)造器創(chuàng)建對象,能通過Field對象直接訪問并修改對象的屬性值
通過反射來生成對象有如下兩種方式:
a) 使用Class對象的newInstance()方法來創(chuàng)建該Class對象對應(yīng)類的實例,這種方法要求該Class對象的對應(yīng)類有默認構(gòu)造器,而執(zhí)行newInstance()方法時實際上是利用默認構(gòu)造器來創(chuàng)建該類的實例
b) 先利用Class對象獲取指定的Constructor對象,再調(diào)用Constructor對象的newInstance()方法來創(chuàng)建該Class對象對應(yīng)類的實例,通過這種方式可以選擇使用某個類的制定構(gòu)造器來創(chuàng)建實例
6、實際上只有當程序需要動態(tài)地創(chuàng)建該對象時才會考慮使用反射,通常在開發(fā)通用性比較廣的框架和基礎(chǔ)平臺時可能會大量使用反射
7、當獲得某個類對應(yīng)的Class對象后,就可以通過該Class對象的getMethods()方法或者getMethod()方法來獲取全部或指定方法----這兩個方法的返回值是Method對象數(shù)組,或者Method對象
每個Method對象包含一個方法,獲得Method對象后,程序就可通過該Method來調(diào)用對應(yīng)方法,在Method里包含一個invoke方法
Obejct invoke(Object obj, Object …args);該方法中的obj是執(zhí)行該方法的主調(diào),后面的args是執(zhí)行該方法時傳入該方法的實參
當通過Method的invoke方法來調(diào)用對應(yīng)的方法時,Java會要求程序必須有調(diào)用該方法的權(quán)限,如果程序確實需要調(diào)用某個對象的invoke方法,可以先調(diào)用Method對象的如下方法:
setAccessible(boolean flag):將flag對象的accessible標志設(shè)置為指示的Boolean值
true表示該Method在使用時應(yīng)該取消Java語言訪問權(quán)限檢查
8、訪問屬性值
通過對象的getFields()或getField()方法可以獲取該類所包括的全部Field(屬性)或指定的Field,Field提供如下兩組方法來訪問屬性:
getXxx(Object obj):獲取obj對象該Field的屬性值
setXxx(Object obj, Xxx val):將obj對象的該Field設(shè)置成val值
使用這兩個方法可以隨意地訪問指定對象的所有屬性,包括private訪問控制的屬性
必須通過setAccessible(true)取消訪問前檢查
9、操作數(shù)組
在java.lang.reflect包下還提供了一個Array類,Array對象可以代表所有的數(shù)組
10、使用反射生成JDK動態(tài)代理
在Java的java.lang.reflect包下提供了一個Proxy類和一個InvocationHandler接口,通過使用這個類和接口可以生成JDK動態(tài)代理類或動態(tài)代理對象
Proxy提供了
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h):直接創(chuàng)建一個動態(tài)代理對象,該代理對象的實現(xiàn)類實現(xiàn)了interfaces指定的系列接口,執(zhí)行代理對象的每個方法時都會被替換執(zhí)行InvocationHandler對象的invoke方法
通常而言,當我們使用Proxy生成一個動態(tài)代理時,往往并不會憑空產(chǎn)生一個動態(tài)代理,通常都是為制定的目標對象來生成動態(tài)代理
這種動態(tài)代理在AOP(Aspect Orient Program,即面向切面編程)里被稱為AOP代理,AOP代理可代替目標對象,AOP代理包含了目標對象的全部方法,但AOP代理中的方法與目標對象的方法存在差異:AOP代理里的方法可以在執(zhí)行目標方法之前,之后插入一些通用處理
希望通過本文的介紹,能夠給你帶來幫助。