框架底層的那些不為人知的密碼之Java反射機(jī)制

一、反射的概敘

什么是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框架。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容