JAVA核心技術(shù)學(xué)習(xí)筆記--反射

反射

反射庫(reflection library)提供了一個(gè)非常豐富且精心設(shè)計(jì)的工具集或舞,以便編寫能夠動(dòng)態(tài)操縱Java代碼的程序。
使用反射蒙幻,能在設(shè)計(jì)或者在添加新類的時(shí)候映凳,能夠快速應(yīng)用開發(fā)工具動(dòng)態(tài)的查詢新添加類的能力。

能夠分析類能力的程序稱為 反射 反射功能極其強(qiáng)大可以用來

  • 在運(yùn)行時(shí)分析類的能力
  • 在運(yùn)行時(shí)查看對(duì)象
  • 實(shí)現(xiàn)通用的數(shù)組來操作代碼
  • 利用Method對(duì)象邮破,此對(duì)象很類似C++中的函數(shù)指針

1,前提介紹: Class 類

在程序運(yùn)行期間诈豌,Java運(yùn)行時(shí)系統(tǒng)始終為所有對(duì)象維護(hù)一個(gè)被稱為運(yùn)行時(shí)的類型標(biāo)識(shí),這個(gè)信息跟蹤著每個(gè)對(duì)象專屬的類抒和。
Class類就是用來專門保存這些類的信息矫渔,通過Object類中的getClass()方法得到每個(gè)類的Class類實(shí)例

Person p;
Class cl = p.getClass();

一個(gè)Class類可以用來保存一個(gè)類的屬性,如:

p.setName("ZhangSan");
System.out.print(cl.getName()+" "+p.getName());

此時(shí)程序會(huì)輸出

Person ZhangSan

Class的getName()方法可以得到這個(gè)類的類名。

獲得類的Class實(shí)例的第2種方法:Class.forName(類名)

String className = "com.henu.Person";
Class cl = Class.forName(className);

第三種方法摧莽,直接 類名.class

Class class1 = Person.class;
Class class2 = Random.class;

通過獲得的Class實(shí)例再創(chuàng)建類的實(shí)例

Class cl = p.getClass();
Perons p = cl.newInstance();

以上代碼在使用時(shí)要放在try catch代碼塊里庙洼,來處理捕獲的異常


2,利用反射分析類的能力,檢查類的結(jié)構(gòu)

java.lang.reflect包中有三個(gè)類

  • Field 描述類的域 getType()方法可以返回描述域所屬類型的Class對(duì)象
  • Method 描述類的方法
  • Constructor 描述類的構(gòu)造器

這三個(gè)類都有一個(gè)getModifiers的方法镊辕,描述各自的訪問修飾符,public private final...等油够,
再通過Modifier類中的isPublic,isPrivate,isXxx方法對(duì)其進(jìn)行判斷.

  • getFields

  • getMethods

  • getConstructors
    這三個(gè)方法分別返回類提供的public域,方法,構(gòu)造器數(shù)組征懈,其中包括超類的共有成員.

  • getDeclareFields

  • getDeclareMethods

  • getDeclaredConstructors
    這三個(gè)方法將返回類中聲明的全部域石咬,方法和構(gòu)造器,包括private,protect,但不包括超類的共有成員

在運(yùn)行時(shí)使用反射分析對(duì)象

接下來進(jìn)一步查看數(shù)據(jù)域的實(shí)際內(nèi)容給

Person p = new Person("張三",20);
Class cl = p.getClass();
Field name = cl.getDeclaredField("name");//獲得Person 類的name域;

Object value = name.get(p); // 此時(shí)value = "張三"


值的注意的一點(diǎn)是卖哎,若name域在Person類中是私有的碌补,代碼會(huì)拋出異常,我們需要對(duì)獲得的數(shù)據(jù)域進(jìn)行設(shè)置


Person p = new Person("張三",20);
Class cl = p.getClass();
Field name = cl.getDeclaredField("name");//獲得Person 類的name域;

name.setAccessible(true);

Object value = name.get(p); // 此時(shí)value = "張三"

setAccessible方法是AccessibleObject類中的一個(gè)方法,它是Field,Method,Constructor類的共有超類棉饶,是為了調(diào)試厦章,持久存儲(chǔ)和相似調(diào)試提供的.

若數(shù)據(jù)域是基本數(shù)據(jù)類型,可以使用域.getDouble(類的實(shí)例),getInt(類的實(shí)例),也可以繼續(xù)使用get( )方法照藻,反射機(jī)制會(huì)自動(dòng)的將這個(gè)域值裝箱袜啃,變成Double,Integer幸缕。

.set(obj,value)方法可以將obj對(duì)象的指定域進(jìn)行賦值

name.set(p,"李四")//此時(shí)p對(duì)象的name為李四

3,使用反射編寫泛型數(shù)組代碼

java.lang.reflect包中的Array類允許動(dòng)態(tài)的創(chuàng)建數(shù)組
以前我們學(xué)過Arrays類中有個(gè)copyOf()方法群发,可以用來拓展已經(jīng)滿了的數(shù)組.

Person[ ] team = new Person[10];

team = Arrays.copyOf(team,2*team.length);  

我們可以用反射寫一個(gè)通用的拓展數(shù)組長度的方法晰韵,能拓展任意類型的數(shù)組。
首先我們寫一個(gè)錯(cuò)誤的例子

public static Object[] badCopyOf(Object[] a,int newLength) {
    Object[] newArray = new Object[newLength];
    System.arrayCopy(a,0,newArray,0,Math.min(a.length,newLength));//第四個(gè)參數(shù)是要從原數(shù)組復(fù)制元素的個(gè)數(shù)
    return newArray;
}

為什么這個(gè)代碼是錯(cuò)的呢熟妓,因?yàn)檫@個(gè)函數(shù)返回的數(shù)組類型是對(duì)象數(shù)組類型(Object [])
一個(gè)對(duì)象數(shù)組不能轉(zhuǎn)化成特定的類的數(shù)組(Object[]->person[]),這樣做會(huì)產(chǎn)生異常雪猪,其實(shí),當(dāng)我們把Person[]轉(zhuǎn)化成 Object[] 再轉(zhuǎn)化成Person[]是可以的起愈,但是一個(gè)一開始就是Object[]的數(shù)組是不能轉(zhuǎn)的,我們可以通過下面這個(gè)方法

Object newArray = Array.newInstance(componentType,int newLength);

java.lang.reflect.Array中的靜態(tài)方法newInstance方法能夠構(gòu)造新的數(shù)組只恨,第一個(gè)參數(shù)是元素的類型,第二個(gè)是數(shù)組長度抬虽。所以現(xiàn)在我們需要獲得新數(shù)組的元素類型和數(shù)組長度官觅。

  • 獲得數(shù)組的長度可以通過.getLength()或者Array.getLength(數(shù)組)獲得
  • 獲得數(shù)組的元素類型可以通過Class類的getComponentType()獲得

所以我們現(xiàn)在要實(shí)現(xiàn)一個(gè)通用的拓展任意類型的方法要經(jīng)過3步

  1. 首先獲得數(shù)組的Class對(duì)象
  2. 確認(rèn)它是一個(gè)數(shù)組類型(通過Class類的isArray()方法)
  3. 使用Class類的getComponentType()方法確定數(shù)組的類型
public static Object goodCopyOf(Object a,int newLength) {
    Class cl = p.getClass();
    if (cl.isArray()) return null;//如果不是數(shù)組類型就結(jié)束
    
    Class componentType = cl.getComponentType();//獲得數(shù)組的元素類型
    int length = a.getLength();
    Object newArray = Array.newInstance(componentType,length);
    System.arrayCopy(a,0,newArray,0,Math.min(length,newLength));
    return newArray;
}

這樣這個(gè)方法就可以用了來拓展任意類型的數(shù)組了

int[] a = {1,2,3,4,5};
a = (int [])goodCopyOf(a,10);

通過Method的invoke方法調(diào)用類的任意方法

兩個(gè)方法
Method method = Person.getClass().getMethod(方法名,方法的參數(shù)類型.class)
method.invoke(方法隸屬的類的實(shí)例,方法的參數(shù)值)

//動(dòng)態(tài)構(gòu)造InvokeTest類的實(shí)例
Class<?> classType = InvokeTest.class;
Object invokeTest = classType.newInstance();

//動(dòng)態(tài)構(gòu)造InvokeTest類的add(int num1, int num2)方法,標(biāo)記為addMethod的Method對(duì)象
Method addMethod = classType.getMethod("add", new Class[]{int.class, int.class});

//動(dòng)態(tài)構(gòu)造的Method對(duì)象invoke委托動(dòng)態(tài)構(gòu)造的InvokeTest對(duì)象阐污,執(zhí)行對(duì)應(yīng)形參的add方法
Object result = addMethod.invoke(invokeTest, new Object[]{1, 2});
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末休涤,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子笛辟,更是在濱河造成了極大的恐慌功氨,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,718評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件手幢,死亡現(xiàn)場(chǎng)離奇詭異疑故,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)弯菊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來踱阿,“玉大人管钳,你說我怎么就攤上這事∪砩啵” “怎么了才漆?”我有些...
    開封第一講書人閱讀 158,207評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長佛点。 經(jīng)常有香客問我醇滥,道長,這世上最難降的妖魔是什么超营? 我笑而不...
    開封第一講書人閱讀 56,755評(píng)論 1 284
  • 正文 為了忘掉前任鸳玩,我火速辦了婚禮,結(jié)果婚禮上演闭,老公的妹妹穿的比我還像新娘不跟。我一直安慰自己,他們只是感情好米碰,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評(píng)論 6 386
  • 文/花漫 我一把揭開白布窝革。 她就那樣靜靜地躺著购城,像睡著了一般。 火紅的嫁衣襯著肌膚如雪虐译。 梳的紋絲不亂的頭發(fā)上瘪板,一...
    開封第一講書人閱讀 50,050評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音漆诽,去河邊找鬼侮攀。 笑死,一個(gè)胖子當(dāng)著我的面吹牛拴泌,可吹牛的內(nèi)容都是我干的魏身。 我是一名探鬼主播,決...
    沈念sama閱讀 39,136評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼蚪腐,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼箭昵!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起回季,我...
    開封第一講書人閱讀 37,882評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤家制,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后泡一,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體颤殴,經(jīng)...
    沈念sama閱讀 44,330評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評(píng)論 2 327
  • 正文 我和宋清朗相戀三年鼻忠,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了涵但。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,789評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡帖蔓,死狀恐怖矮瘟,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情塑娇,我是刑警寧澤澈侠,帶...
    沈念sama閱讀 34,477評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站埋酬,受9級(jí)特大地震影響哨啃,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜写妥,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評(píng)論 3 317
  • 文/蒙蒙 一拳球、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧珍特,春花似錦醇坝、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽画畅。三九已至,卻和暖如春宋距,著一層夾襖步出監(jiān)牢的瞬間轴踱,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評(píng)論 1 267
  • 我被黑心中介騙來泰國打工谚赎, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留淫僻,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,598評(píng)論 2 362
  • 正文 我出身青樓壶唤,卻偏偏與公主長得像雳灵,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子闸盔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評(píng)論 2 351

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

  • 第一章:Java程序設(shè)計(jì)概述 Java和C++最大的不同在于Java采用的指針模型可以消除重寫內(nèi)存和損壞數(shù)據(jù)的可能...
    loneyzhou閱讀 1,243評(píng)論 1 7
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法悯辙,類相關(guān)的語法,內(nèi)部類的語法迎吵,繼承相關(guān)的語法躲撰,異常的語法,線程的語...
    子非魚_t_閱讀 31,602評(píng)論 18 399
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理击费,服務(wù)發(fā)現(xiàn)拢蛋,斷路器,智...
    卡卡羅2017閱讀 134,638評(píng)論 18 139
  • 一 國慶節(jié)回即墨老家蔫巩,老家還有一畝七分土地谆棱,按照往年,家里一般會(huì)種一畝花生圆仔、七分玉米垃瞧。今年春天因?yàn)樘鞖飧稍铮咸爝t...
    堂小訶德閱讀 1,046評(píng)論 6 10
  • 今天是什么日子 起床:7:45 就寢:23:00 天氣:微風(fēng)不燥荧缘,陽光正好。 心情:平和簡單 紀(jì)念日:無 任務(wù)清單...
    楠澧閱讀 217評(píng)論 2 3