淺談反射

反射機(jī)制作用

  1. 在運(yùn)行時(shí)分析類的能力
  2. 在運(yùn)行時(shí)查看對(duì)象
  3. 實(shí)現(xiàn)通用的數(shù)組操作代碼

反射機(jī)制的實(shí)現(xiàn)

采用Class類和java.lang.reflect 類庫(kù)一起實(shí)現(xiàn) <反射>機(jī)制

  1. Class 類: 代表一個(gè)目標(biāo)類鸳劳。
  2. Field 類: 代表目標(biāo)類的成員變量碴卧。
  3. Method 類: 代表目標(biāo)類的方法。
  4. Constructor 類: 代表目標(biāo)類的構(gòu)造方法维贺。
  5. Array 類: 提供了動(dòng)態(tài)創(chuàng)建數(shù)組就乓,以及訪問(wèn)數(shù)組的元素的靜態(tài)方法妓柜。

Class 類

? 在程序運(yùn)行期間澳泵,Java運(yùn)行時(shí)系統(tǒng)始終為所有的對(duì)象維護(hù)一個(gè)被稱為運(yùn)行時(shí)的類型表示玄柏。這個(gè)信息跟蹤著每個(gè)對(duì)象所屬的類。虛擬機(jī)利用運(yùn)行時(shí)類型信息選擇相應(yīng)的方法執(zhí)行满败。

? 然而窘奏,可以通過(guò)專門(mén)的Java類訪問(wèn)這些信息。保存這些信息的類被成為Class葫录,這個(gè)名字很容易讓人混淆着裹。Object 類中的getClass() 方法將返回一個(gè)Class類型的實(shí)例。

獲取Class對(duì)象的三種方法

  • 如果類在一個(gè)包里,包的名字也作為做類名的一部分骇扇。
Random generator = new Random();
Class cl = generator.getClass();
System.out.println(cl.getName());//java.util.Random
  • 如果類名保存字符串中摔竿,并可在運(yùn)行時(shí)該變,即可使用這種方法少孝。forName() 方法會(huì)爆ClassNotFoundException 異常继低,所以需要進(jìn)行異常處理。

    Class.forName() 內(nèi)部通過(guò)反射API根據(jù)目標(biāo)類名將類手動(dòng)加載到內(nèi)存中稍走,稱為類加載器加載方法袁翁。加載過(guò)程中會(huì)把目標(biāo)類的static方法,變量婿脸,代碼塊加載到JVM粱胜,注意此時(shí)尚未創(chuàng)建對(duì)象實(shí)例

 String className = "java.util.Random";
 Class cl = class.forName(className);
  • 如果T是任意的Java類型(或void 關(guān)鍵字),T.class 將代表匹配的類對(duì)象
 Class cl = Random.class;

獲取構(gòu)造器--Constructor 類

  • Constructor[] getConstructors():獲得所有public構(gòu)造器狐树;
  • Constructor[] getDeclaredConstructors():獲得所有訪問(wèn)權(quán)限的構(gòu)造器
  • Constructor getConstructor(Class[] params):根據(jù)指定參數(shù)獲得對(duì)應(yīng)構(gòu)造器焙压;
  • Constructor getDeclaredConstructor(Class[] params):根據(jù)指定參數(shù)獲得對(duì)應(yīng)構(gòu)造器;

獲得方法--Method 類

  • Method[] getMethods():獲得所有public方法抑钟;
  • Method[] getDeclaredMethods():獲得所有訪問(wèn)權(quán)限的方法涯曲;
  • Method getMethod(String name, Class[] params):根據(jù)方法簽名獲取類自身對(duì)應(yīng)public方法,或者從基類繼承和接口實(shí)現(xiàn)的對(duì)應(yīng)public方法在塔;
  • Method getDeclaredMethod(String name, Class[] params):根據(jù)方法簽名獲得對(duì)應(yīng)的類自身聲明方法幻件,訪問(wèn)權(quán)限不限

獲得變量--Field 類

  • Field[] getFields():獲得類中所有public變量
  • Field[] getDeclaredFields():獲得類中所有訪問(wèn)權(quán)限變量
  • Field getField(String name):根據(jù)變量名得到對(duì)應(yīng)的public變量
  • Field getDeclaredField(String name):根據(jù)變量名獲得對(duì)應(yīng)的變量蛔溃,訪問(wèn)權(quán)限不限傲武;

實(shí)戰(zhàn)

我們來(lái)個(gè)例子加深一下印象。

打印一個(gè)類的所有構(gòu)造函數(shù)

public static void printConstructors(Class cl)
   {
       //返回包含Constructor 對(duì)象的數(shù)組城榛,其中包含了Class對(duì)象的所有構(gòu)造器
       Constructor[] constructors = cl.getDeclaredConstructors();

       for (Constructor c: constructors) {
           //String getName()
           //返回一個(gè)用于描述構(gòu)造器揪利、方法或域名的字符串
           String name = c.getName();
           System.out.print("    ");
           String modifiers = Modifier.toString(c.getModifiers());
           if (modifiers.length()>0)
               System.out.print(modifiers+ "  ");
           System.out.print(name+"(");
           //Class[] getParameterTypes() (在Constructor 和 Method 類中)
           //返回一個(gè)用于描述參數(shù)類型的Class對(duì)象數(shù)組
           printParameterType(c.getParameterTypes());
           System.out.println(");");
       }
   }

打印一個(gè)類的所有方法

public static void printMethods(Class cl)
   {
       //返回包含Method 對(duì)象的數(shù)組,返回這個(gè)類或接口的全部方法狠持,但不包括由超類繼承了的方法
       Method[] methods = cl.getDeclaredMethods();
       for (Method m:methods) {
           //Class getReturnType() (在 Method 類中)
           //返回一個(gè)用于描述返回類型的Class對(duì)象
           Class retType = m.getReturnType();
           String name = m.getName();

           System.out.print("    ");
           //打印修飾符疟位、返回類型和方法名稱
           String modifiers =Modifier.toString(m.getModifiers());
           if (modifiers.length()>0)
               System.out.print(modifiers+" ");
           System.out.print(retType.getName()+" "+ name + "(");

           printParameterType(m.getParameterTypes());
           System.out.println(");");
       }
   }

打印一個(gè)類的所有字段

public static void printFields(Class cl)
   {
       //Field[] getDeclaredFields()
       //返回包含F(xiàn)ield 對(duì)象的數(shù)組,這些對(duì)象記錄了這個(gè)類的全部域
       Field[] fields = cl.getDeclaredFields();

       for (Field f : fields){
           Class type = f.getType();
           String name = f.getName();
           System.out.print("    ");
           String modifiers = Modifier.toString(f.getModifiers());
           if (modifiers.length()>0)
               System.out.print(modifiers+"  ");
           System.out.println(type.getName()+" "+ name+ ";");
       }
   }

打印方法的參數(shù)類型

public static void printParameterType(Class[] paramTypes)
   {
       for (int j = 0;j<paramTypes.length;j++) {
           if (j>0)
               System.out.print(", ");
           System.out.print(paramTypes[j].getName());
       }
   }

測(cè)試

public static void main(String[] args)
   {
       String name;
       if (args.length>0)
           name = args[0];
       else {
           Scanner in = new Scanner(System.in);
           System.out.println("Enter class name(e.g java.util.Date): ");
           name = in.next();
       }
       try {
           //print class name and superclass name (if != object)
           //調(diào)用Class 的靜態(tài)方法 forName 獲得類名對(duì)應(yīng)的Class 對(duì)象
           Class cl = Class.forName(name);
           //獲取父類所對(duì)應(yīng)的Class 對(duì)象
           Class supercl = cl.getSuperclass();
           //返回對(duì)應(yīng)modifiers 中位設(shè)置的修飾符的字符串表示
           String modifiers = Modifier.toString(cl.getModifiers());

           if (modifiers.length()>0)
               System.out.print(modifiers+"  ");
           System.out.print("class "+ name);
           //判斷是否有繼承父類
           if (supercl != null  && supercl != Object.class)
               System.out.print("  extends "+ supercl.getName());

           System.out.print("\n{\n");
           printConstructors(cl);
           System.out.println();
           printMethods(cl);
           System.out.println();
           printFields(cl);
           System.out.println("}");


       }catch (ClassNotFoundException ex) {
           ex.printStackTrace();
       }
       System.exit(0);
   }

參考

JAVA核心技術(shù)(卷1)原書(shū)第10版

反射筆記

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末喘垂,一起剝皮案震驚了整個(gè)濱河市甜刻,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌正勒,老刑警劉巖得院,帶你破解...
    沈念sama閱讀 211,123評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異章贞,居然都是意外死亡祥绞,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)蜕径,“玉大人两踏,你說(shuō)我怎么就攤上這事《涤鳎” “怎么了梦染?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,723評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)朴皆。 經(jīng)常有香客問(wèn)我帕识,道長(zhǎng),這世上最難降的妖魔是什么遂铡? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,357評(píng)論 1 283
  • 正文 為了忘掉前任肮疗,我火速辦了婚禮,結(jié)果婚禮上忧便,老公的妹妹穿的比我還像新娘族吻。我一直安慰自己帽借,他們只是感情好珠增,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著砍艾,像睡著了一般蒂教。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上脆荷,一...
    開(kāi)封第一講書(shū)人閱讀 49,760評(píng)論 1 289
  • 那天凝垛,我揣著相機(jī)與錄音,去河邊找鬼蜓谋。 笑死梦皮,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的桃焕。 我是一名探鬼主播剑肯,決...
    沈念sama閱讀 38,904評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼观堂!你這毒婦竟也來(lái)了让网?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,672評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤师痕,失蹤者是張志新(化名)和其女友劉穎溃睹,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體胰坟,經(jīng)...
    沈念sama閱讀 44,118評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡因篇,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片惜犀。...
    茶點(diǎn)故事閱讀 38,599評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡铛碑,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出虽界,到底是詐尸還是另有隱情汽烦,我是刑警寧澤,帶...
    沈念sama閱讀 34,264評(píng)論 4 328
  • 正文 年R本政府宣布莉御,位于F島的核電站撇吞,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏礁叔。R本人自食惡果不足惜牍颈,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望琅关。 院中可真熱鬧煮岁,春花似錦、人聲如沸涣易。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,731評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)新症。三九已至步氏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間徒爹,已是汗流浹背荚醒。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,956評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留隆嗅,地道東北人界阁。 一個(gè)月前我還...
    沈念sama閱讀 46,286評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像胖喳,于是被迫代替她去往敵國(guó)和親泡躯。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評(píng)論 2 348

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

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理禀晓,服務(wù)發(fā)現(xiàn)精续,斷路器,智...
    卡卡羅2017閱讀 134,628評(píng)論 18 139
  • Scala與Java的關(guān)系 Scala與Java的關(guān)系是非常緊密的4饫痢重付! 因?yàn)镾cala是基于Java虛擬機(jī),也就是...
    燈火gg閱讀 3,424評(píng)論 1 24
  • 一般的理療館,大多都沒(méi)有自主開(kāi)發(fā)客戶的習(xí)慣披泪,更多的是靠群體口碑來(lái)傳播纤子,也就是說(shuō),通過(guò)治療自身的問(wèn)題毛病款票,得到相應(yīng)好...
    王小嘉1閱讀 1,862評(píng)論 0 0
  • 2018年2月22日 星期四 晴 旭和梅是我牽紅線促成的第一對(duì)控硼,今天見(jiàn)到了他們的兒子。非嘲伲可愛(ài)的小家伙 卡乾,是一個(gè)為...
    韶憶閱讀 138評(píng)論 0 0
  • 親愛(ài)的寶貝,今天是你出生后的105天缚够,原諒媽媽那么長(zhǎng)時(shí)間沒(méi)有記錄你的成長(zhǎng)幔妨。2018年1月12號(hào)你來(lái)到這個(gè)世界上,...
    才才的小壞蛋閱讀 165評(píng)論 0 0