五月天青色头像情侣网名,国产亚洲av片在线观看18女人,黑人巨茎大战俄罗斯美女,扒下她的小内裤打屁股

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

用最直接的大白話來聊一聊Java中的反射機(jī)制

2020-12-08 11:38 作者:每天一個禿頂小技巧  | 我要投稿

用最通俗易懂的話來說一說Java中的反射機(jī)制
思考:在講反射之前,先思考一個問題,java中如何創(chuàng)建一個對象,有哪幾種方式?
Java中創(chuàng)建對象大概有這幾種方式:
1、使用new關(guān)鍵字:這是我們最常見的也是最簡單的創(chuàng)建對象的方式
2、使用Clone的方法:無論何時我們調(diào)用一個對象的clone方法,JVM就會創(chuàng)建一個新的對象,將前面的對象的內(nèi)容全部拷貝進(jìn)去
3、使用反序列化:當(dāng)我們序列化和反序列化一個對象,JVM會給我們創(chuàng)建一個單獨的對象
上邊是Java中常見的創(chuàng)建對象的三種方式,其實除了上邊的三種還有另外一種方式,就是接下來我們要討論的?“反射”
1、反射概述
1.1什么是反射
反射就是把Java類中的各個部分,映射成一個個的Java對象,拿到這些對象后可以做一些事情。
既然說反射是反射Java類中的各個組成部分,所以說咱們得知道一個類中有哪兒些部分?
例如,一個類有:成員變量,方法,構(gòu)造方法,等信息,利用反射技術(shù)咱們可以把這些組成部分映射成一個個對象。
1.2、反射能干什么
說完反射的概念后,咱們說一下反射能干什么?
一般來說反射是用來做框架的,或者說可以做一些抽象度比較高的底層代碼,反射在日常的開發(fā)中用到的不多,但是咱們還必須搞懂它,因為搞懂了反射以后,可以幫助咱們理解框架的一些原理。所以說有一句很經(jīng)典的話:反射是框架設(shè)計的靈魂。現(xiàn)在說完這個可能還不太能理解,不急,等下說完一個快速入門的例子后,應(yīng)該會稍微有點感覺
1.3、怎么得到想反射的類
剛才已經(jīng)說過,反射是對一個類進(jìn)行解剖,想解剖一個東西,前提是首先你得拿到這個東西,那么怎么得到咱們想解剖的類呢?
首先大家要明白一點,咱們寫的代碼是存儲在后綴名是 .java的文件里的,但是它會被編譯,最終真正去執(zhí)行的是編譯后的 .class文件。Java是面向?qū)ο蟮恼Z言,一切皆對象,所以java認(rèn)為 這些編譯后的 class文件,這種事物也是一種對象,它也給抽象成了一種類,這個類就是Class,大家可以去AIP里看一下這個類


所以拿到這個類后,就相當(dāng)于拿到了咱們想解剖的類,那怎么拿到這個類?


看API文檔后,有一個方法forName(String className); 而且是一個靜態(tài)的方法,這樣咱們就可以得到想反射的類了


到這里,看Class clazz = Class.forName("com.cj.test.Person");這個應(yīng)該有點感覺了吧
Class.forName("com.cj.test.Person");因為這個方法里接收的是個字符串,字符串的話,我們就可以寫在配置文件里,然后利用反射生成我們需要的對象,這才是我們想要的。很多框架里都有類似的配置
2、解剖類
我們知道一個類里一般有構(gòu)造函數(shù)、方法、成員變量(字段/屬性)這三部分組成
翻閱API文檔,可以看到
Class對象提供了如下常用方法:
public Constructor getConstructor(Class<?>…parameterTypes)
public Method getMethod(String name,Class<?>… parameterTypes)
public Field getField(String name)
public Constructor getDeclaredConstructor(Class<?>…parameterTypes)
public Method getDeclaredMethod(String name,Class<?>… parameterTypes)
public Field getDeclaredField(String name)
這些方法分別用于幫咱們從類中解剖出構(gòu)造函數(shù)、方法和成員變量(屬性)。
然后把解剖出來的部分,分別用Constructor、Method、Field對象表示。
2.1反射構(gòu)造方法
2.1.1反射無參的構(gòu)造函數(shù)



可以看到 默認(rèn)的無參構(gòu)造方法執(zhí)行了
從上邊的例子看出,要想反射,首先第一步就是得到類的字節(jié)碼
所以簡單說一下得到類的字節(jié)碼的幾種方式
(1)、Class.forName("com.cj.test.Person"); 這就是上邊我們用的方式
(2)、對象.getClass();
(3)、類名.class;


2.1.2反射“一個參數(shù)”的構(gòu)造函數(shù)


2.1.3反射“多個參數(shù)”的構(gòu)造函數(shù)


2.1.4反射“私有”的構(gòu)造函數(shù)


注意:在反射私有的構(gòu)造函數(shù)時,用普通的clazz.getConstructor()會報錯,因為它是私有的,所以提供了專門反射私有構(gòu)造函數(shù)的方法?clazz.getDeclaredConstructor(int.class);//讀取私有的構(gòu)造函數(shù),用這個方法讀取完還需要設(shè)置一下暴力反射才可以
c.setAccessible(true);//暴力反射
2.1.5反射得到類中所有的構(gòu)造函數(shù)

*****注意:看下上邊代碼里test6和test7的invoke方法里傳的參數(shù)和其他的有點不一樣
這是因為 jdk1.4和jdk1.5處理invoke方法有區(qū)別
1.5:public Object invoke(Object obj,Object…args)
1.4:public Object invoke(Object obj,Object[] args)
由于JDK1.4和1.5對invoke方法的處理有區(qū)別, 所以在反射類似于main(String[] args) 這種參數(shù)是數(shù)組的方法時需要特殊處理
啟動Java程序的main方法的參數(shù)是一個字符串?dāng)?shù)組,即public static void main(String[] args),通過反射方式來調(diào)用這個main方法時,如何為invoke方法傳遞參數(shù)呢?按jdk1.5的語法,整個數(shù)組是一個參數(shù),而按jdk1.4的語法,數(shù)組中的每個元素對應(yīng)一個參數(shù),當(dāng)把一個字符串?dāng)?shù)組作為參數(shù)傳遞給invoke方法時,javac會到底按照哪種語法進(jìn)行處理呢?jdk1.5肯定要兼容jdk1.4的語法,會按jdk1.4的語法進(jìn)行處理,即把數(shù)組打散成為若干個單獨的參數(shù)。所以,在給main方法傳遞參數(shù)時,不能使用代碼mainMethod.invoke(null,new String[]{“xxx”}),javac只把它當(dāng)作jdk1.4的語法進(jìn)行理解,而不把它當(dāng)作jdk1.5的語法解釋,因此會出現(xiàn)參數(shù)個數(shù)不對的問題。
上述問題的解決方法:
(1)mainMethod.invoke(null,new Object[]{new String[]{"xxx"}});
這種方式,由于你傳的是一個數(shù)組的參數(shù),所以為了向下兼容1.4的語法,javac遇到數(shù)組會給你拆開成多個參數(shù),但是由于咱們這個Object[ ] 數(shù)組里只有一個元素值,所以就算它拆也沒關(guān)系
(2)mainMethod.invoke(null,(Object)new String[]{"xxx"});
這種方式相當(dāng)于你傳的參數(shù)是一個對象,而不是數(shù)組,所以就算是按照1.4的語法它也不會拆,所以問題搞定
編譯器會作特殊處理,編譯時不把參數(shù)當(dāng)作數(shù)組看待,也就不會數(shù)組打散成若干個參數(shù)了
對上邊的描述進(jìn)行一下總結(jié):在反射方法時,如果方法的參數(shù)是一個數(shù)組,考慮到向下兼容問題,會按照J(rèn)DK1.4的語法來對待(JVM會把傳遞的數(shù)組參數(shù)拆開,拆開就會報參數(shù)的個數(shù)不匹配的錯誤)
解決辦法:防止JVM拆開你的數(shù)組
方式一:把數(shù)組看做是一個Object對象
方式二:重新構(gòu)建一個Object數(shù)組,那個參數(shù)數(shù)組作為唯一的元素存在。
2.3反射類中的屬性字段

以上就是自己對Java中反射的一些學(xué)習(xí)總結(jié),歡迎大家留言一起學(xué)習(xí)、討論
看完上邊有關(guān)反射的東西, 對常用框架里的配置文件是不是有點思路了


上邊是Spring配置文件里的常見的bean配置,這看起來是不是可以用反射很輕易的就可以實現(xiàn):解析xml然后把xml里的內(nèi)容作為參數(shù),利用反射創(chuàng)建對象。
拓展:
1、除了上述的Spring配置文件里會用到反射生成bean對象,其他常見的MVC框架,比如Struts2、SpringMVC等等一些框架里還有很多地方都會用到反射。
前端夜頁面錄入的一些信息通過表單或者其他形式傳入后端,后端框架就可以利用反射生成對應(yīng)的對象,并利用反射操作它的set、get方法把前端傳來的信息封裝到對象里。
2、框架的代碼里經(jīng)常需要利用反射來操作對象的set、get方法,來把程序的數(shù)據(jù)封裝到Java對象中去。
如果每次都使用反射來操作對象的set、get方法進(jìn)行設(shè)置值和取值的話,過于麻煩,所以JDK里提供了一套API,專門用于操作Java對象的屬性(set/get方法),這就是內(nèi)省
3、平常用到的框架,除了配置文件的形式,現(xiàn)在很多都使用了注解的形式。
其實注解也和反射息息相關(guān):使用反射也能輕而易舉的拿到類、字段、方法上的注解,然后編寫注解解析器對這些注解進(jìn)行解析,做一些相關(guān)的處理
所以說不管是配置文件還是注解的形式,它們都和反射有關(guān)。注解和自定義注解的內(nèi)容,最近也抽時間大概整理了一下,感興趣的小可愛可以點擊了解:Java中的注解以及自定義注解
寫在最后:反射是框架的靈魂,具備反射知識和思想,是看懂框架的基礎(chǔ)。希望看完文章后對你能有所幫助。
親們,可以點關(guān)注,點贊,3Q~


原文轉(zhuǎn)自網(wǎng)絡(luò),侵刪

想要了解更多可以點擊:

尚學(xué)堂最新2020版Java300集教程課程_

用最直接的大白話來聊一聊Java中的反射機(jī)制的評論 (共 條)

分享到微博請遵守國家法律
广昌县| 白朗县| 安化县| 沂南县| 三穗县| 平湖市| 安岳县| 阿拉善盟| 昌邑市| 色达县| 遂溪县| 庐江县| 新巴尔虎右旗| 漠河县| 白沙| 石楼县| 咸阳市| 苍溪县| 安福县| 新平| 文登市| 资溪县| 故城县| 贵阳市| 碌曲县| 临城县| 九江市| 娱乐| 东丽区| 固原市| 高雄县| 库尔勒市| 朝阳区| 呼和浩特市| 额济纳旗| 柞水县| 盐亭县| 长兴县| 固始县| 和田市| 阳西县|