|
一、java的反射機(jī)制淺談
最近研究java研究得很給力,主要以看博文為學(xué)習(xí)方式。以下是我對java的反射機(jī)制所產(chǎn)生的一些感悟,希望各位童鞋看到失誤之處不吝指出。受到各位指教之處,如若讓小生好好感動,說不定會請各位吃飯哦!
1.何謂反射機(jī)制
根據(jù)網(wǎng)文,java中的反射機(jī)制可以如此定義:
JAVA反射機(jī)制是在運(yùn)行狀態(tài)中,對于任意一個(gè)類,都能夠知道這個(gè)類的所有屬性和方法;對于任意一個(gè)對象,都能夠調(diào)用它的任意一個(gè)方法;這種動態(tài)獲取的信息以及動態(tài)調(diào)用對象的方法的功能稱為java語言的反射機(jī)制。
2.反射機(jī)制如何實(shí)現(xiàn)
談到反射機(jī)制,最誘人的莫過于“動態(tài)”二字了。接觸過C語言的童鞋們都知道,C語言中也有個(gè)和“動態(tài)”搭上邊的函數(shù):malloc()函數(shù)。其實(shí)這里的兩個(gè)動態(tài)是一個(gè)意思,都指的是非編譯時(shí)處理,抑或運(yùn)行時(shí)處理。這種機(jī)制,可以讓程序的彈性增加不少,因?yàn)榻栌纱藱C(jī)制,客戶可以在程序運(yùn)行時(shí)改變一些他關(guān)心的性質(zhì):分配內(nèi)存(當(dāng)然他可能 完全不知道這么做了),調(diào)用某個(gè)類(當(dāng)然他還是被蒙在鼓里)等。
下面我們就聊聊java中動態(tài)機(jī)制是如何實(shí)現(xiàn)的。
上一篇文章中提到了java的類的加載問題,但沒有更深入地解釋其運(yùn)行機(jī)制,在這里就先談?wù)勥@個(gè)問題。
首先不得不提到的是java.lang.Class這個(gè)類。
有這么一段話:
Java程序在運(yùn)行時(shí),Java運(yùn)行時(shí)系統(tǒng)一直對所有的對象進(jìn)行所謂的運(yùn)行時(shí)類型標(biāo)識。這項(xiàng)信息紀(jì)錄了每個(gè)對象所屬的類。虛擬機(jī)通常使用運(yùn)行時(shí)類型信息選準(zhǔn)正確方法去執(zhí)行,用來保存這些類型信息的類是Class類。
也就是說,ClassLoader找到了需要調(diào)用的類時(shí)(java為了調(diào)控內(nèi)存的調(diào)用消耗,類的加載都在需要時(shí)再進(jìn)行,很摳但是很有效),就會加載它,然后根據(jù).class文件內(nèi)記載的類信息來產(chǎn)生一個(gè)與該類相聯(lián)系的獨(dú)一無二的Class對象。該Class對象記載了該類的字段,方法等等信息。以后jvm要產(chǎn)生該類的實(shí)例,就是根據(jù)內(nèi)存中存在的該Class類所記載的信息(Class對象應(yīng)該和我所了解的其他類一樣會在堆內(nèi)存內(nèi)產(chǎn)生、消亡)來進(jìn)行。
而java中的Class類對象是可以人工自然性的(也就是說開放的)得到的(雖然你無法像其他類一樣運(yùn)用構(gòu)造器來得到它的實(shí)例,因?yàn)?br />
Class對象都是jvm產(chǎn)生的。不過話說回來,客戶產(chǎn)生的話也是無意義的),而且,更偉大的是,基于這個(gè)基礎(chǔ),java實(shí)現(xiàn)了反射機(jī)制。
獲取Class對象有三種方式:
1.通過Object類的getClass()方法。例如:
Class c1 = new String("").getClass();
2.通過Class類的靜態(tài)方法——forName()來實(shí)現(xiàn):
Class c2 = Class.forName("MyObject");
3.如果T是一個(gè)已定義的類型的話,在java中,它的.class文件名:T.class就代表了與其匹配的Class對象,例如:
Class c3 = Manager.class;
Class c4 = int.class;
Class c5 = Double[].class;
這里需要解釋一下3:請記住一句話,java中,一切皆對象。也就是說,基本類型int float 等也會在jvm的內(nèi)存池像其他類型一樣中生成
一個(gè)Class對象。而數(shù)組等組合型數(shù)據(jù)類型也是會生成一個(gè)Class對象的,而且更令人驚訝的是,java中數(shù)組的本來面目其實(shí)就是某個(gè)類,驚訝
中的驚訝是,含有相同元素的相同維數(shù)的數(shù)組還會共同享用同一個(gè)Class對象!其實(shí)根據(jù)我的臆想,數(shù)組的length性質(zhì)應(yīng)該就保存在這個(gè)Class
對象里面。
Class類中存在以下幾個(gè)重要的方法:
1.getName()
一個(gè)Class對象描述了一個(gè)特定類的特定屬性,而這個(gè)方法就是返回String形式的該類的簡要描述。由于歷史原因,對數(shù)組的Class對象
調(diào)用該方法會產(chǎn)生奇怪的結(jié)果。
2.newInstance()
該方法可以根據(jù)某個(gè)Class對象產(chǎn)生其對應(yīng)類的實(shí)例。需要強(qiáng)調(diào)的是,它調(diào)用的是此類的默認(rèn)構(gòu)造方法。例如:
MyObject x = new MyObject();
MyObject y = x.getClass().newInstance();
3.getClassLoader()
返回該Class對象對應(yīng)的類的類加載器。
4.getComponentType()
該方法針對數(shù)組對象的Class對象,可以得到該數(shù)組的組成元素所對應(yīng)對象的Class對象。例如:
int[] ints = new int[]{1,2,3};
Class class1 = ints.getClass();
Class class2 = class1.getComponentType();
而這里得到的class2對象所對應(yīng)的就應(yīng)該是int這個(gè)基本類型的Class對象。
5.getSuperClass()
返回某子類所對應(yīng)的直接父類所對應(yīng)的Class對象。
6.isArray()
判定此Class對象所對應(yīng)的是否是一個(gè)數(shù)組對象。
好啦,現(xiàn)在對Class這個(gè)類應(yīng)該有了一個(gè)大致的了解,下面就給出一個(gè)反射機(jī)制的典型例子供各位分析:
- import java.lang.reflect.Array;
- import java.lang.reflect.Constructor;
- import java.lang.reflect.Field;
- import java.lang.reflect.Method;
-
-
- /**
- * Java Reflection Cookbook
- *
- * @author Michael Lee
- * @since 2006-8-23
- * @version 0.1a
- */
-
- public class Reflection {
- /**
- * 得到某個(gè)對象的公共屬性
- *
- * @param owner, fieldName
- * @return 該屬性對象
- * @throws Exception
- *
- */
- public Object getProperty(Object owner, String fieldName) throws Exception {
- Class ownerClass = owner.getClass();
-
- Field field = ownerClass.getField(fieldName);
-
- Object property = field.get(owner);
-
- return property;
- }
-
- /**
- * 得到某類的靜態(tài)公共屬性
- *
- * @param className 類名
- * @param fieldName 屬性名
- * @return 該屬性對象
- * @throws Exception
- */
- public Object getStaticProperty(String className, String fieldName)
- throws Exception {
- Class ownerClass = Class.forName(className);
-
- Field field = ownerClass.getField(fieldName);
-
- Object property = field.get(ownerClass);
-
- return property;
- }
-
-
- /**
- * 執(zhí)行某對象方法
- *
- * @param owner
- * 對象
- * @param methodName
- * 方法名
- * @param args
- * 參數(shù)
- * @return 方法返回值
- * @throws Exception
- */
- public Object invokeMethod(Object owner, String methodName, Object[] args)
- throws Exception {
-
- Class ownerClass = owner.getClass();
-
- Class[] argsClass = new Class[args.length];
-
- for (int i = 0, j = args.length; i < j; i++) {
- argsClass[i] = args[i].getClass();
- }
-
- Method method = ownerClass.getMethod(methodName, argsClass);
-
- return method.invoke(owner, args);
- }
-
-
- /**
- * 執(zhí)行某類的靜態(tài)方法
- *
- * @param className
- * 類名
- * @param methodName
- * 方法名
- * @param args
- * 參數(shù)數(shù)組
- * @return 執(zhí)行方法返回的結(jié)果
- * @throws Exception
- */
- public Object invokeStaticMethod(String className, String methodName,
- Object[] args) throws Exception {
- Class ownerClass = Class.forName(className);
-
- Class[] argsClass = new Class[args.length];
-
- for (int i = 0, j = args.length; i < j; i++) {
- argsClass[i] = args[i].getClass();
- }
-
- Method method = ownerClass.getMethod(methodName, argsClass);
-
- return method.invoke(null, args);
- }
-
-
-
- /**
- * 新建實(shí)例
- *
- * @param className
- * 類名
- * @param args
- * 構(gòu)造函數(shù)的參數(shù)
- * @return 新建的實(shí)例
- * @throws Exception
- */
- public Object newInstance(String className, Object[] args) throws Exception {
- Class newoneClass = Class.forName(className);
-
- Class[] argsClass = new Class[args.length];
-
- for (int i = 0, j = args.length; i < j; i++) {
- argsClass[i] = args[i].getClass();
- }
-
- Constructor cons = newoneClass.getConstructor(argsClass);
-
- return cons.newInstance(args);
-
- }
-
-
-
- /**
- * 是不是某個(gè)類的實(shí)例
- * @param obj 實(shí)例
- * @param cls 類
- * @return 如果 obj 是此類的實(shí)例,則返回 true
- */
- public boolean isInstance(Object obj, Class cls) {
- return cls.isInstance(obj);
- }
-
- /**
- * 得到數(shù)組中的某個(gè)元素
- * @param array 數(shù)組
- * @param index 索引
- * @return 返回指定數(shù)組對象中索引組件的值
- */
- public Object getByArray(Object array, int index) {
- return Array.get(array,index);
- }
- }
復(fù)制代碼
例子的解釋就免了,因?yàn)樽x代碼加上自己理解是最好的程序員學(xué)習(xí)方式。另外,此代碼來源為互聯(lián)網(wǎng)。
好啦,就到這里了。當(dāng)你知道了java的反射機(jī)制后,以后當(dāng)你接觸到j(luò)ava的動態(tài)代理時(shí)就不會像我一樣茫然了。好啦,謝謝圍觀!
|
|