JAVA反射较店,用好就這點(diǎn)東西

在Java中,想要運(yùn)行時(shí)操作對(duì)象的方法夭问、屬性泽西,其中有效的手段曹铃,就有反射缰趋。這也是框架最常使用的手段,因?yàn)榭蚣茉诰幾g時(shí)并不知曉系統(tǒng)中有哪些類會(huì)被使用陕见。

Java中對(duì)象的類型信息在運(yùn)行時(shí)由Class對(duì)象表示秘血,Class對(duì)象是伴隨類加載而實(shí)例化產(chǎn)生的,而反射的實(shí)現(xiàn)就圍繞著Class對(duì)象评甜。

有很多種方式可以獲取類的Class對(duì)象灰粮,包括:

        Class<Object> c1 = Object.class;
        Class<?> c2 = Class.forName("java.lang.Object");
        Class<?> c3 = new Object().getClass();

反射可以做什么?

1. 實(shí)例化對(duì)象

對(duì)象的實(shí)例化忍坷,可以通過(guò)new關(guān)鍵字直接實(shí)例化粘舟,也可以通過(guò)反射,例如:

class.newInstance() 
class.getConstructor(Class<?>... parameterTypes).newInstance(Object ... initargs)

為什么需要用反射來(lái)進(jìn)行對(duì)象實(shí)例化佩研?

  1. 有不能使用new關(guān)鍵字直接實(shí)例化對(duì)象的場(chǎng)景柑肴,例如:Spring容器管理的Bean,只能通過(guò)類的全限定名加載類旬薯,然后反射實(shí)例化襟交。

  2. 在不想使用new關(guān)鍵字的場(chǎng)景析既,目的是為了簡(jiǎn)化編程结耀,使代碼美觀凤藏,可能大家經(jīng)常看到類似的用法顷编,例如:

//  解析Json
  public static <T> T parseObject(String text, Class<T> clazz) {
      return parseObject(text, clazz, new Feature[0]);
  }
    /**
     * 簡(jiǎn)單的復(fù)制出新類型對(duì)象.
     */
    public static <S, D> D map(S source, Class<D> destinationClass) {
        return mapper.map(source, destinationClass);
    }

2. 篩選合適的類

實(shí)際開(kāi)發(fā)中,經(jīng)常會(huì)有這種需要,如果類有某某特征扬跋,就進(jìn)行某某操作。
在Spring進(jìn)行掃描的時(shí)候凌节,我們會(huì)通過(guò)過(guò)濾器胁住,來(lái)精細(xì)化控制bean的生成,包括:根據(jù)isInstance(Object obj)判斷是否實(shí)現(xiàn)某某接口或者繼承特殊的父類刊咳;根據(jù)isAnnotationPresent(Class<? extends Annotation> annotationClass)判斷是否被注解標(biāo)記彪见。

3. 方法調(diào)用

有些場(chǎng)景不能或者不合適直接調(diào)用方法,例如:我們處理HTTP請(qǐng)求娱挨,需要從URI映射到方法調(diào)用余指,如果我們能夠窮舉所有的URL到對(duì)象方法的映射關(guān)系,那么也沒(méi)問(wèn)題跷坝,但是無(wú)數(shù)的if條件判斷酵镜,顯然不是明智的選擇。通常我們先會(huì)獲取資源對(duì)象柴钻,然后反射調(diào)用對(duì)象的方法淮韭。

Method.invoke(Object obj, Object... args)

如何獲取對(duì)象的方法對(duì)象,也就是Method對(duì)象呢贴届?Class類提供了以下實(shí)現(xiàn):

Method[] getMethods();
Method[] getDeclaredMethods();
Method getMethod(String name, Class<?>... parameterTypes);
Method getDeclaredMethod(String name, Class<?>... parameterTypes);

這些方法可以分為兩類:
一靠粪、方法簽名中帶有Declared得,會(huì)在當(dāng)前類的所有方法中查找毫蚓,但不會(huì)遍歷父類占键。
二、不帶Declared的會(huì)遍歷所有父類元潘,但只會(huì)查找public方法畔乙。

推薦使用工具類:org.apache.commons.lang3.reflect.MethodUtils
此類中包含遍歷所有父類查找方法、當(dāng)前類查找public方法或者反射執(zhí)行方法的便捷操作翩概。

4. 屬性操作

Class.getFields(), Class.getField(String), 
Class.getDeclaredFields(), Class.getDeclaredField(String)

命名規(guī)則同方法牲距,推薦使用工具類:org.apache.commons.lang3.FieldUtils,進(jìn)行讀取或者賦值操作钥庇。
反射進(jìn)行賦值有幾點(diǎn)需要注意:

  • 如果不為public類型牍鞠,那么設(shè)置字段前必須通過(guò)Field.setAccessible(true)方法進(jìn)行訪問(wèn)權(quán)限設(shè)置,不然會(huì)拋出異常:IllegalAccessException 上沐。
  • 如果字段為static類型皮服,那么通過(guò)set方法進(jìn)行賦值時(shí),會(huì)忽略obj對(duì)象,因?yàn)殪o態(tài)字段屬于類龄广。
  • 如果字段為final類型硫眯,不管是public還是 private,那么用set方法賦值時(shí)择同,只有setAccessible進(jìn)行訪問(wèn)權(quán)限設(shè)置后两入,才能正確調(diào)用,不然會(huì)報(bào)異常:IllegalAccessException敲才。但是對(duì)final字段進(jìn)行set方法賦值時(shí)裹纳,盡管方法正常調(diào)用,但是并不會(huì)改變fianl字段的值紧武。
  • 如果字段為final static 類型剃氧,那么進(jìn)行set方法賦值時(shí),總會(huì)拋出IllegalAccessException異常阻星。

最后如果對(duì)當(dāng)前對(duì)象的所有方法朋鞍,或者所有字段進(jìn)行某種操作,那么推薦工具類:org.springframework.util.ReflectionUtils妥箕。本人在RPC中動(dòng)態(tài)代理一文中有使用滥酥。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市畦幢,隨后出現(xiàn)的幾起案子坎吻,更是在濱河造成了極大的恐慌,老刑警劉巖宇葱,帶你破解...
    沈念sama閱讀 218,525評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瘦真,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡贝搁,警方通過(guò)查閱死者的電腦和手機(jī)吗氏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)雷逆,“玉大人,你說(shuō)我怎么就攤上這事污尉“蛘埽” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,862評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵被碗,是天一觀的道長(zhǎng)某宪。 經(jīng)常有香客問(wèn)我,道長(zhǎng)锐朴,這世上最難降的妖魔是什么兴喂? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,728評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上衣迷,老公的妹妹穿的比我還像新娘畏鼓。我一直安慰自己,他們只是感情好壶谒,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布云矫。 她就那樣靜靜地躺著,像睡著了一般汗菜。 火紅的嫁衣襯著肌膚如雪让禀。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,590評(píng)論 1 305
  • 那天陨界,我揣著相機(jī)與錄音巡揍,去河邊找鬼。 笑死菌瘪,一個(gè)胖子當(dāng)著我的面吹牛吼肥,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播麻车,決...
    沈念sama閱讀 40,330評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼缀皱,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了动猬?” 一聲冷哼從身側(cè)響起啤斗,我...
    開(kāi)封第一講書(shū)人閱讀 39,244評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎赁咙,沒(méi)想到半個(gè)月后钮莲,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,693評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡彼水,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評(píng)論 3 336
  • 正文 我和宋清朗相戀三年崔拥,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片凤覆。...
    茶點(diǎn)故事閱讀 40,001評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡链瓦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出盯桦,到底是詐尸還是另有隱情慈俯,我是刑警寧澤,帶...
    沈念sama閱讀 35,723評(píng)論 5 346
  • 正文 年R本政府宣布拥峦,位于F島的核電站贴膘,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏略号。R本人自食惡果不足惜刑峡,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評(píng)論 3 330
  • 文/蒙蒙 一洋闽、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧突梦,春花似錦诫舅、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,919評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至撮奏,卻和暖如春俏讹,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背畜吊。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,042評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工泽疆, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人玲献。 一個(gè)月前我還...
    沈念sama閱讀 48,191評(píng)論 3 370
  • 正文 我出身青樓殉疼,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親捌年。 傳聞我的和親對(duì)象是個(gè)殘疾皇子瓢娜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 三重:代碼、底層內(nèi)存礼预、源碼 第一階段:開(kāi)發(fā)常用JavaSE基礎(chǔ)眠砾、IDE、Maven托酸、Gradle褒颈、SVN、Git励堡、...
    guodd369閱讀 16,548評(píng)論 1 44
  • 《親愛(ài)的安德烈》讀書(shū)筆記 親愛(ài)的寶寶: 今天和你一起去打壁球谷丸,很幸運(yùn)的蹭了你的課,回家外公問(wèn)你感覺(jué)怎樣应结,你說(shuō)覺(jué)得很...
    花子姐姐閱讀 484評(píng)論 1 1
  • 從希臘回來(lái)就感覺(jué)周圍的世界在騷動(dòng)刨疼,那股勁兒紅紅火火恍恍惚惚持續(xù)著,直至上禮拜到杭州培訓(xùn)一周回來(lái)后~的今天【微笑】摊趾。...
    慢六不慢熱閱讀 209評(píng)論 0 1
  • 1币狠、橫向思維 當(dāng)我們遇到困難的時(shí)候,更多的應(yīng)該是換一種思路去思考砾层,不能只認(rèn)死理,一根筋到底的死磕贱案!有時(shí)候肛炮,你站在現(xiàn)...
    鄧成渝閱讀 211評(píng)論 0 1
  • 在這個(gè)有些潮濕有些冷清有些灰暗的上午侨糟,一杯咖啡伴著一篇文章碍扔,時(shí)光飛逝著,情緒波動(dòng)著秕重。讀著《昨日不同,我哭泣》的前言,隨...
    七月風(fēng)閱讀 588評(píng)論 3 9