一、反射的概敘
什么是Java的反射機(jī)制?
? ? ? ? 反射是Java的特征之一,是一種間接操作目標(biāo)對象的機(jī)制,核心是JVM在運(yùn)行的時(shí)候才動態(tài)加載類,并且對于任意一個(gè)類,都能夠知道這個(gè)類的所有屬性和方法,調(diào)用方法/訪問屬性,不需要提前在編譯期知道運(yùn)行的對象是誰,他允許運(yùn)行中的Java程序獲取類的信息,并且可以操作類或?qū)ο髢?nèi)部屬性。程序中對象的類型一般都是在編譯期就確定下來的,而當(dāng)我們的程序在運(yùn)行時(shí),可能需要動態(tài)的加載一些類,這些類因?yàn)橹坝貌坏?,所以沒有加載到j(luò)vm,這時(shí),使用Java反射機(jī)制可以在運(yùn)行期動態(tài)的創(chuàng)建對象并調(diào)用其屬性,它是在運(yùn)行時(shí)根據(jù)需要才加載。
Java反射機(jī)制的作用?
允許編程人員在對類未知的情況下,獲取類相關(guān)信息的方式變得更加多樣靈活,調(diào)用類中相應(yīng)方法,是Java增加其靈活性與動態(tài)性的一種機(jī)制(從.class --> .java)。
反射機(jī)制的優(yōu)缺點(diǎn)?
優(yōu)點(diǎn):
????????使用反射,我們就可以在運(yùn)行時(shí)獲得類的各種內(nèi)容,進(jìn)行反編譯,對于Java這種先編譯再運(yùn)行的語言,能夠讓我們很方便的創(chuàng)建靈活的代碼,這些代碼可以在運(yùn)行時(shí)裝配,無需在組件之間進(jìn)行源代碼的鏈接,更加容易實(shí)現(xiàn)面向?qū)ο蟆?/p>
缺點(diǎn):
1、性能問題。
????????Java反射機(jī)制中包含了一些動態(tài)類型,所以Java虛擬機(jī)不能夠?qū)@些動態(tài)代碼進(jìn)行優(yōu)化。因此,反射操作的效率要比正常操作效率低很多。我們應(yīng)該避免在對性能要求很高的程序或經(jīng)常被執(zhí)行的代碼中使用反射。而且,如何使用反射決定了性能的高低。如果它作為程序中較少運(yùn)行的部分,性能將不會成為一個(gè)問題。
2、安全限制。
????????使用反射通常需要程序的運(yùn)行沒有安全方面的限制。如果一個(gè)程序?qū)Π踩蕴岢鲆?,則最好不要使用反射。
3、程序健壯性。
????????反射允許代碼執(zhí)行一些通常不被允許的操作,所以使用反射有可能會導(dǎo)致意想不到的后果。反射代碼破壞了Java程序結(jié)構(gòu)的抽象性,所以當(dāng)程序運(yùn)行的平臺發(fā)生變化的時(shí)候,由于抽象的邏輯結(jié)構(gòu)不能被識別,代碼產(chǎn)生的效果與之前會產(chǎn)生差異。同時(shí)也會使得程序的代碼復(fù)雜度上升,所以還要我們慎重的使用它。
二、反射的基本使用
sun為反射機(jī)制提供的常用的類
? ??????Java.lang.Class;?
?? ?????Java.lang.reflect.Constructor;??
? ??????Java.lang.reflect.Field;
? ??????Java.lang.reflect.Method;?
? ??????Java.lang.reflect.Modifier;
反射常用的API?
????對象. setAccessible(true);// 修改訪問權(quán)限
Class:
????類對象.getField("屬性名");?? //獲取公開屬性
????類對象.getDeclaredField("屬性名");? //獲取私有屬性
????類對象.getMethod("方法名", null); //通過指定方法名稱獲取公開無參方法對象
????類對象.getMethods(); //獲取所有公開方法對象
????類對象.getDeclaredMethods(); //獲取所有方法對象
????類對象.getDeclaredMethod("方法名", 方法參數(shù)的類型......); //通過指定方法名稱獲取私有有參方法對象
????類對象.getConstructor(構(gòu)造參數(shù)類型); //調(diào)用公開有參構(gòu)造
????類對象.getDeclaredConstructor(構(gòu)造參數(shù)類型); //調(diào)用私有有參構(gòu)造
????類對象.isInstance(obj);// 判斷是否是某個(gè)類的實(shí)例
Field:
????屬性對象.getName(); //獲取屬性名
????屬性對象.getType(); ////獲取屬性的類型
????屬性對象.getModifiers(); //獲取屬性的修飾符
????屬性對象.set(obj,obj); //設(shè)置屬性值 1:類實(shí)例化對象 要設(shè)置的參數(shù)值
????……
Method:
?????? 方法對象.invoke(類實(shí)例化對象, 方法的參數(shù)數(shù)組);? //執(zhí)行方法
Constructor:
?????? NewInstance();//通過構(gòu)造獲取到類的實(shí)例對象
三、站在反射的角度看待ORM框架
ORM框架的簡單實(shí)現(xiàn)(JDBC部分):
? ? jdbc連接類:

? ? ? ? CRUD基類:
? ? ? ? ? ? 得到增加SQL的方法:


? ??????增加方法:

? ??????查詢方法:


????從以上代碼可以看出我們只需要傳入一個(gè)Object對象就可以對數(shù)據(jù)庫進(jìn)行CRUD操作,Object對象是可以為任意實(shí)體類的,所以說這個(gè)類是我們通過反射的機(jī)制來寫的一個(gè)對所有數(shù)據(jù)庫表CRUD的基類。
????類似與ORM框架Hibernate、Mybatis框架底層都是使用反射機(jī)制來保證框架的靈活性。我曾閱讀過這些框架的源碼,底層實(shí)現(xiàn)幾乎就是使用這樣的方式實(shí)現(xiàn)的,只是我這個(gè)實(shí)現(xiàn)寫的有點(diǎn)簡單,大家可以參考我的這篇文章再去看一下框架的源碼,試著自己寫一個(gè)ORM框架。