java基礎(chǔ)-反射技術(shù)(磨礪營(yíng)馬劍威java)

?

在Java運(yùn)行時(shí)環(huán)境中裳凸,對(duì)于任意一個(gè)類薄货,能否知道這個(gè)類的哪些屬性和方法碌奉?對(duì)于任意一個(gè)對(duì)象短曾,能否調(diào)用它的任意一個(gè)方法?答案是肯定的赐劣。這種動(dòng)態(tài)獲取類的信息以及動(dòng)態(tài)調(diào)用對(duì)象的方法的功能來(lái)自于Java語(yǔ)言的反射(Reflection)機(jī)制嫉拐。

反射給java提供了,運(yùn)行時(shí)獲取一個(gè)類實(shí)例的可能魁兼,這一點(diǎn)非常靈活婉徘,你僅僅傳一個(gè)類的全限定名,就能通過(guò)反射璃赡,來(lái)獲取對(duì)應(yīng)的類實(shí)例判哥,我們一般會(huì)用Class類,來(lái)調(diào)用這個(gè)被反射的Objcet類下的:構(gòu)造方法碉考,屬性塌计,或方法等。

反射在一些開源框架里用的非常之多侯谁,Spring锌仅,Struts,Hibnerate墙贱,MyBatics都有它的影子热芹,反射雖然很靈活,能夠使得寫的代碼惨撇,變的大幅精簡(jiǎn)伊脓,所以在用的時(shí)候,一定要注意具體的應(yīng)用場(chǎng)景魁衙。

反射的優(yōu)缺點(diǎn)如下:

優(yōu)點(diǎn):

A:能夠運(yùn)行時(shí)動(dòng)態(tài)獲取類的實(shí)例报腔,大大提高系統(tǒng)的靈活性和擴(kuò)展性。

B:與Java動(dòng)態(tài)編譯相結(jié)合剖淀,可以實(shí)現(xiàn)無(wú)比強(qiáng)大的功能

缺點(diǎn):

A:使用反射的性能較低

B:使用反射相對(duì)來(lái)說(shuō)不安全

C:破壞了類的封裝性纯蛾,可以通過(guò)反射獲取這個(gè)類的私有方法和屬性

任何事物,都有兩面性纵隔,反射的優(yōu)點(diǎn)翻诉,也同是就是它的缺點(diǎn)炮姨,所以,沒(méi)有好與壞碰煌,只有最合適的場(chǎng)景舒岸,一陰一陽(yáng),才是天道平衡的條件拄查。

在反射API中我們重點(diǎn)關(guān)注一下幾個(gè)類:

Class? -- 代表類

Field? -- 代表屬性(成員變量)

Method? -- 代表方法

Constructor? -- 代表構(gòu)造方法

一吁津、Class

Java中不論一個(gè)類產(chǎn)生了多少個(gè)對(duì)象,這些對(duì)象的Class對(duì)象都始終是一個(gè)堕扶。Class對(duì)象中含有該類的任何信息(屬性碍脏,方法,類名稍算,父類典尾,包等),在Java中獲取Class對(duì)象的方法有三種:

// 第一種方法:類名.class

Class ? cla = Student.class;

Class ? as =int.class;?? // 基本數(shù)據(jù)類型唯一能點(diǎn)出的就是class

// 第二種方法:通過(guò)對(duì)象調(diào)用.getClass()

Student ? stu =newStudent();

Class ? c = stu.getClass();

// 第三種方法:通過(guò)類的全限定名獲取

try{

Class ? c1 = Class.forName("entity.Student");

}catch(ClassNotFoundException e) {

e.printStackTrace();

}

System.out.println(cla.getName()); // 全限定名

System.out.println(Modifier.toString(cla.getModifiers()));

System.out.println(cla.getSimpleName());

System.out.println(cla.getPackage().getName());

可以通過(guò)Class對(duì)象產(chǎn)生該類的對(duì)象糊探,如下:

// 獲取Class對(duì)象

Class ? cla = Student.class;

/* 1. 直接創(chuàng)建對(duì)象(調(diào)用默認(rèn)無(wú)參構(gòu)造方法)钾埂,類里必須要有默認(rèn)構(gòu)造方法 */

Object ? obj1 = cla.newInstance();

System.out.println(obj1);

二、Constructor

如果想通過(guò)有參構(gòu)造方法來(lái)創(chuàng)建對(duì)象科平,那么這時(shí)候就得先獲取有參構(gòu)造方法褥紫,再通過(guò)有參構(gòu)造方法來(lái)創(chuàng)建對(duì)象:

// 獲取Class對(duì)象

Class cla = Student.class;

/* 1. 直接創(chuàng)建對(duì)象(調(diào)用默認(rèn)無(wú)參構(gòu)造方法),類里必須要有默認(rèn)構(gòu)造方法 */

Object obj1 = cla.newInstance();

System.out.println(obj1);

/* 2. 通過(guò)無(wú)參構(gòu)造方法創(chuàng)建對(duì)象瞪慧,和第一種方法效果一樣 */

Constructor no = cla.getConstructor(); // 先獲取無(wú)參構(gòu)造方法

Object obj2 = no.newInstance();

System.out.println(obj2);

/* 3. 通過(guò)有參構(gòu)造方法創(chuàng)建對(duì)象 */

Constructor has = cla.getDeclaredConstructor(String.class,int.class); // 形參

Object obj3 = has.newInstance("老李", 23); // 傳入的是實(shí)參

System.out.println(obj3);

三髓考、Field

Field代表是類中的屬性,我們可以獲取屬性弃酌,并修改其值(注:先得有對(duì)象才能修改值氨菇,另:修改沒(méi)權(quán)限的屬性時(shí),需要先打開該屬性的權(quán)限)妓湘。

// 獲取Class對(duì)象

Class cla =newStudent().getClass();

// 獲取構(gòu)造方法

Constructor con = cla.getConstructor(String.class,int.class);

// 創(chuàng)建對(duì)象

Object obj = con.newInstance("如來(lái)", 222);

// 獲取要操作的屬性

Field name = cla.getDeclaredField("name");

// 反射操作private屬性的時(shí)候查蓉,需要打開權(quán)限

name.setAccessible(true);

// 獲取obj的name屬性值

System.out.println(name.get(obj));

// 把obj的name屬性值改為:菩提

name.set(obj, "菩提");

System.out.println(name.get(obj));

// 把id設(shè)置為10086

Field id = cla.getDeclaredField("id");

id.set(obj, 10086);

System.out.println(id.get(obj))

四、Method

Method代表類中的方法榜贴,和Field操作類型:

// 獲取Class對(duì)象

Class cla = Student.class;

// 創(chuàng)建對(duì)象

Object obj = cla.getDeclaredConstructor(String.class,int.class).newInstance("達(dá)摩", 666);

// 獲取要操作的方法

Method showNo = cla.getDeclaredMethod("show");

Method showHas = cla.getDeclaredMethod("show", String.class);

Method calc = cla.getDeclaredMethod("calc",int.class,double.class);

calc.setAccessible(true);

// 調(diào)用方法

showNo.invoke(obj);

showHas.invoke(obj, "老衲");

Object value = calc.invoke(obj, 10086, Math.PI);

System.out.println(value);

我們可以用反射來(lái)改進(jìn)簡(jiǎn)單工廠模式:

packagedemo08;

importjava.io.FileInputStream;

importjava.util.Properties;

publicclassPetFactory {

publicstaticvoidmain(String[] args) {

System.out.println(getInstance("dog")); ?// demo08.Dog@67a9b034

}

// 工廠方法

publicstaticPet ? getInstance(String tag) {

Properties ? p =newProperties();

try{

p.load(newFileInputStream("conf/pet.properties"));

}catch(Exception e) {

System.out.println("加載配置文件錯(cuò)誤豌研!");

}

String ? className = p.getProperty(tag);

try{

// 利用反射創(chuàng)建對(duì)象

Class ? cla = Class.forName(className);

return(Pet)cla.newInstance();

}catch(ClassNotFoundException e) {

System.out.println("無(wú)法識(shí)別您的標(biāo)識(shí)!");

}catch(InstantiationException e) {

e.printStackTrace();

}catch(IllegalAccessException e) {

e.printStackTrace();

}

returnnull;

}

}

classPet {}

classDogextendsPet {}

classCatextendsPet {}

classPenguinextendsPet {}

conf/pet.properties文件內(nèi)容如下:

dog=demo08.Dog

cat=demo08.Cat

penguin=demo08.Penguin

這里的配置文件為.properties,稱作屬性文件唬党。通過(guò)反射讀取里邊的內(nèi)容鹃共。這樣代碼是固定的,但是配置文件的內(nèi)容我們可以改初嘹,這樣使我們的代碼靈活了很多及汉!

綜上JAVA反射的再次學(xué)習(xí)沮趣,靈活的運(yùn)用它屯烦,能夠使我們的代碼更加靈活,但是它也有它的缺點(diǎn),就是運(yùn)用它會(huì)使我們的軟件的性能降低驻龟,復(fù)雜度增加温眉,所以還要我們慎重的使用它。

更多內(nèi)容關(guān)注微信公眾號(hào)mjw-java或訪問(wèn)www.moliying.com

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末翁狐,一起剝皮案震驚了整個(gè)濱河市类溢,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌露懒,老刑警劉巖闯冷,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異懈词,居然都是意外死亡蛇耀,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門坎弯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)纺涤,“玉大人,你說(shuō)我怎么就攤上這事抠忘×么叮” “怎么了?”我有些...
    開封第一講書人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵崎脉,是天一觀的道長(zhǎng)拧咳。 經(jīng)常有香客問(wèn)我,道長(zhǎng)荧嵌,這世上最難降的妖魔是什么呛踊? 我笑而不...
    開封第一講書人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮啦撮,結(jié)果婚禮上谭网,老公的妹妹穿的比我還像新娘。我一直安慰自己赃春,他們只是感情好愉择,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著织中,像睡著了一般锥涕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上狭吼,一...
    開封第一講書人閱讀 51,562評(píng)論 1 305
  • 那天层坠,我揣著相機(jī)與錄音,去河邊找鬼刁笙。 笑死破花,一個(gè)胖子當(dāng)著我的面吹牛谦趣,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播座每,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼前鹅,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了峭梳?” 一聲冷哼從身側(cè)響起舰绘,我...
    開封第一講書人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎葱椭,沒(méi)想到半個(gè)月后捂寿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡孵运,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年者蠕,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片掐松。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡踱侣,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出大磺,到底是詐尸還是另有隱情抡句,我是刑警寧澤,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布杠愧,位于F島的核電站待榔,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏流济。R本人自食惡果不足惜锐锣,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望绳瘟。 院中可真熱鬧雕憔,春花似錦、人聲如沸糖声。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蘸泻。三九已至琉苇,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間悦施,已是汗流浹背并扇。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留抡诞,地道東北人穷蛹。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓渗勘,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親俩莽。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

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

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法乔遮,類相關(guān)的語(yǔ)法扮超,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法蹋肮,異常的語(yǔ)法出刷,線程的語(yǔ)...
    子非魚_t_閱讀 31,632評(píng)論 18 399
  • 一、概述 Java反射機(jī)制定義 Java反射機(jī)制是在運(yùn)行狀態(tài)中坯辩,對(duì)于任意一個(gè)類馁龟,都能夠知道這個(gè)類中的所有屬性和方法...
    CoderZS閱讀 1,636評(píng)論 0 26
  • 1. 了解 Java 中的反射 1.1 什么是 Java 的反射 Java 反射是可以讓我們?cè)谶\(yùn)行時(shí)獲取類的函數(shù)、...
    Ten_Minutes閱讀 537評(píng)論 0 4
  • (一)Java部分 1漆魔、列舉出JAVA中6個(gè)比較常用的包【天威誠(chéng)信面試題】 【參考答案】 java.lang;ja...
    獨(dú)云閱讀 7,105評(píng)論 0 62
  • 1.jdbc是什么坷檩,它有什么用? java database connection 讓java程序員可以直接通過(guò)j...
    yeller閱讀 569評(píng)論 0 2