反射

以試題為入手點:

  1. 什么是反射機制?
    簡單說,反射機制指的是程序在運行時能夠獲取自身的信息与斤。在java中,只要給定類的名字荚恶,那么就可以通過反射機制來獲得類的所有信息。

  2. java反射機制提供了什么功能磷支?

  • 在運行時能夠判斷任意一個對象所屬的類
  • 在運行時構(gòu)造任意一個類的對象
  • 在運行時判斷任意一個類所具有的成員變量和方法
  • 在運行時調(diào)用任一對象的方法
  • 在運行時創(chuàng)建新類對象
  1. 哪里用到反射機制谒撼?
    jdbc中有一行代碼:Class.forName('com.MySQL.jdbc.Driver.class').newInstance();那個時候只知道生成驅(qū)動對象實例,后來才知道雾狈,這就是反射廓潜,現(xiàn)在很多框架都用到反射機制,hibernate善榛,struts都是用反射機制實現(xiàn)的辩蛋。

  2. 反射機制的優(yōu)缺點?

  • 靜態(tài)編譯:在編譯時確定類型移盆,綁定對象悼院,即通過
  • 動態(tài)編譯:運行時確定類型,綁定對象咒循。動態(tài)編譯最大限度的發(fā)揮了java的靈活性据途,體現(xiàn)了多態(tài)的應(yīng)用,有利于降低類之間的耦合性叙甸。

一句話颖医,反射機制的優(yōu)點就是可以實現(xiàn)動態(tài)創(chuàng)建對象和編譯,體現(xiàn)出很大的靈活性裆蒸,特別是在J2EE的開發(fā)中它的靈活性就表現(xiàn)的十分明顯熔萧。比如,一個大型的軟件,不可能一次就把把它設(shè)計的很完美佛致,當(dāng)這個程序編譯后遂赠,發(fā)布了,當(dāng)發(fā)現(xiàn)需要更新某些功能時晌杰,我們不可能要用戶把以前的卸載跷睦,再重新安裝新的版本,假如這樣的話,這個軟件肯定是沒有多少人用的。采用靜態(tài)的話碧信,需要把整個程序重新編譯一次才可以實現(xiàn)功能的更新朽色,而采用反射機制的話,它就可以不用卸載雏吭,只需要在運行時才動態(tài)的創(chuàng)建和編譯,就可以實現(xiàn)該功能。
它的缺點是對性能有影響层玲。使用反射基本上是一種解釋操作,我們可以告訴JVM反症,我們希望做什么并且它滿足我們的要求辛块。這類操作總是慢于只直接執(zhí)行相同的操作。

  1. 動態(tài)加載類
  • 編譯時加載類是靜態(tài)加載類铅碍,new 創(chuàng)建對象是靜態(tài)加載類润绵,在編譯時刻就需要加載所有可用使用到的類,如果有一個用不了胞谈,那么整個文件都無法通過編譯
  • 運行時加載類是動態(tài)加載類尘盼。Class c = Class.forName("類的全名"),不僅表示了類的類型烦绳,還表示了動態(tài)加載類卿捎,編譯不會報錯,在運行時才會加載径密,使用接口標(biāo)準(zhǔn)能更方便動態(tài)加載類的實現(xiàn)午阵。功能性的類盡量使用動態(tài)加載,而不用靜態(tài)加載睹晒。
  • 很多軟件比如QQ,360的在線升級趟庄,并不需要重新編譯文件,只是動態(tài)的加載新的東西
  1. 如何使用java的反射?
  • a. 通過一個全限類名創(chuàng)建一個對象
    • Class.forName("全限類名"); 例如:com.mysql.jdbc.Driver Driver類已經(jīng)被加載到 jvm中伪很,并且完成了類的初始化工作就行了 //可以在未知對象情況下使用戚啥,可能會有一個ClassNotFoundException異常
    • 類名.class; 獲取Class<?> clz 對象 //實際告訴我們?nèi)魏我粋€類都有一個隱含的靜態(tài)成員變量class(知道類名時用)
    • 對象.getClass(); //已知該類的對象通過getClass方法(知道對象時用)
  • b. 獲取構(gòu)造器對象锉试,通過構(gòu)造器new出一個對象
    • Clazz.getConstructor([String.class]);
    • Con.newInstance([參數(shù)]);
  • c. 通過class對象創(chuàng)建一個實例對象(就相當(dāng)與new類名()無參構(gòu)造器)
    • Clazz.newInstance();
  • d. 通過class對象獲得一個屬性對象
    • Field c=clz.getFields():獲得某個類的所有的公共(public)的字段猫十,包括父類中的字段。
    • Field c=clz.getDeclaredFields():獲得某個類的所有聲明的字段,即包括public拖云、private和proteced贷笛,但是不包括父類的申明字段 e.
  • e、通過class對象獲得一個方法對象
    • Clazz.getMethod("方法名",class…..parameaType);(只能獲取公共的)
    • Clazz.getDeclareMethod("方法名");(獲取任意修飾的方法宙项,不能執(zhí)行私有)
    • M.setAccessible(true);(讓私有的方法可以執(zhí)行)
  • f乏苦、 讓方法執(zhí)行
    • Method.invoke(obj實例對象,obj可變參數(shù));-----(是有返回值的)
  1. 獲取方法信息
  • 1、基本的數(shù)據(jù)類型尤筐,void關(guān)鍵字都存在類類型
1 Class c1 =int.class;//int的類類型
2 Class c2 =String.class;//String類的類類型汇荐,可以理解為編譯生成的那個String.class字節(jié)碼文件,
3 //當(dāng)然盆繁,這并不是官方的說法
4 Class c3 =double.class;
5 Class c4 =Double.class;
6 Class c5 =void.class;
  • 2掀淘、Class類的基本API操作
/**
    * 打印類的信息,包括類的成員函數(shù)油昂,成員變量
* @param obj 該對象所屬類的信息
*/
publicstaticvoid printClassMessage(Object obj){
//要獲取類的信息革娄,首先要獲取類的類類型
Class c = obj.getClass();//傳遞的是哪個子類的對象,c就是該子類的類類型
//獲取類的名稱
System.out.println("累的名稱是:"+c.getName());

/*
    * Method類冕碟,方法的對象
* 一個成員方法就是一個Method對象
* getMethods()方法獲取的是所有的public的函數(shù)拦惋,包括父類繼承而來的
* getDeclaredMethods()獲取的是多有該類自己聲明的方法,不問訪問權(quán)限
*/
Method[] ms = c.getMethods();//c.getDeclaredMethods();
for(int i =0; i < ms.length; i++){
//得到方法的返回值類型的類類型
Class retrunType = ms[i].getReturnType();
System.out.print(retrunType.getName()+" ");
//得到方法的名稱
System.out.print(ms[i].getName()+"(");
//獲取的參數(shù)類型--->得到的是參數(shù)列表的類型的類類型
Class[] paraTypes = ms[i].getParameterTypes();
for(Class class1 : paraTypes){
System.out.print(class1.getName()+",");
}
System.out.println(")");
}
}

8.獲取成員變量構(gòu)造函數(shù)信息

/**
    * 成員變量也是對象鸣哀,是java.lang.reflect.Field這個類的的對象
* Field類封裝了關(guān)于成員變量的操作
* getFields()方法獲取的是所有public的成員變量的信息
* getDeclareFields()方法獲取的是該類自己聲明的成員變量的信息
*/
Field[] fs = c.getDeclaredFields();
for(Field field : fs){
//得到成員變量的類型的類類型
Class fieldType = field.getType();
String typeName = fieldType.getName();
//得到成員變量的名稱
String fieldName = field.getName();
System.out.print(typeName+" "+fieldName);
}
/**
    * 構(gòu)造函數(shù)也是對象
* java.lang.Constructor中封裝了構(gòu)造函數(shù)的信息
* getConstructor()方法獲取所有的public的構(gòu)造函數(shù)
* getDeclaredConstructors得到所有的構(gòu)造函數(shù)
*/
Constructor[] cs = c.getDeclaredConstructors();
for(Constructor constructor : cs){
System.out.print(constructor.getName()+"(");
//獲取構(gòu)造函數(shù)的參數(shù)列表---》得到的是參數(shù)雷彪的類類型
Class[] paramTypes = constructor.getParameterTypes();
for(Class class1 : paramTypes){
System.out.print(class1.getName()+",");
}
System.out.println(")");
}

9.方法反射的基本操作

1架忌、如何獲取某個方法
方法的名稱和方法的參數(shù)列表才能唯一決定某個方法。Method m = c.getDeclaredMethod("方法名"我衬,可變參數(shù)列表(參數(shù)類型.class))
2、方法的反射操作
m.invoke(對象饰恕,參數(shù)列表)挠羔,方法如果沒有返回值,返回null埋嵌,如果有返回值返回Object類型破加,然后再強制類型轉(zhuǎn)換為原函數(shù)的返回值類型

10.通過反射了解集合泛型的本質(zhì)

ArrayList list1 =new ArrayList();
ArrayList<String> list2 =new ArrayList<String>();

Class c1 = list1.getClass();
Class c2 = list2.getClass();

System.out.println(c1==c2);//結(jié)果為true,為什么雹嗦?范舀?

結(jié)果分析:因為反射的操作都是編譯之后的操作,也就是運行時的操作了罪,c1==c2返回true锭环,說明編譯之后集合的泛型是去泛型化的。那么我們就可以理解為泊藕,Java集合中的泛型辅辩,是用于防止錯誤類型元素輸入的,比如在list2中我們add一個int,add(10)就會編譯報錯玫锋,那么這個泛型就可以只在編譯階段有效蛾茉,通過了編譯階段,泛型就不存在了撩鹿∏妫可以驗證,我們繞過編譯节沦,用反射動態(tài)的在list2中add一個int是可以成功的键思,只是這時因為list2中存儲了多個不同類型的數(shù)據(jù)(String型,和int型)散劫,就不能用for-each來遍歷了稚机,會拋出類型轉(zhuǎn)換錯誤異常ClassCastException

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市获搏,隨后出現(xiàn)的幾起案子赖条,更是在濱河造成了極大的恐慌,老刑警劉巖常熙,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件纬乍,死亡現(xiàn)場離奇詭異,居然都是意外死亡裸卫,警方通過查閱死者的電腦和手機仿贬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來墓贿,“玉大人茧泪,你說我怎么就攤上這事×” “怎么了队伟?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長幽勒。 經(jīng)常有香客問我嗜侮,道長,這世上最難降的妖魔是什么啥容? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任锈颗,我火速辦了婚禮,結(jié)果婚禮上咪惠,老公的妹妹穿的比我還像新娘击吱。我一直安慰自己,他們只是感情好硝逢,可當(dāng)我...
    茶點故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布姨拥。 她就那樣靜靜地躺著绅喉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪叫乌。 梳的紋絲不亂的頭發(fā)上柴罐,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天,我揣著相機與錄音憨奸,去河邊找鬼革屠。 笑死,一個胖子當(dāng)著我的面吹牛排宰,可吹牛的內(nèi)容都是我干的似芝。 我是一名探鬼主播,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼板甘,長吁一口氣:“原來是場噩夢啊……” “哼党瓮!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起盐类,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤寞奸,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后在跳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體枪萄,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年猫妙,在試婚紗的時候發(fā)現(xiàn)自己被綠了瓷翻。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡割坠,死狀恐怖齐帚,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情彼哼,我是刑警寧澤童谒,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站沪羔,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏象浑。R本人自食惡果不足惜蔫饰,卻給世界環(huán)境...
    茶點故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望愉豺。 院中可真熱鬧篓吁,春花似錦、人聲如沸蚪拦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至盛嘿,卻和暖如春洛巢,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背次兆。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工稿茉, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人芥炭。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓漓库,卻偏偏與公主長得像,于是被迫代替她去往敵國和親园蝠。 傳聞我的和親對象是個殘疾皇子渺蒿,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,514評論 2 348