- 相關(guān)推薦
關(guān)于Java的內(nèi)省與反射
很多同學(xué)在深入的接觸Java語(yǔ)言后就會(huì)發(fā)現(xiàn)這樣兩個(gè)詞:反射(Reflection)和內(nèi)省(Introspector),經(jīng)常搞不清楚這到底是怎么回事,在什么場(chǎng)合下應(yīng)用以及如何使用?下面YJBYS小編為大家整理了關(guān)于Java的內(nèi)省與反射的文章,希望對(duì)你有所幫助。
內(nèi)省
內(nèi)省是Java語(yǔ)言對(duì)Bean類屬性、事件的一種缺省處理方法。例如類A中有屬性name,那我們可以通過(guò)getName,setName來(lái)得到其值或者設(shè)置新的值。通過(guò)getName/setName來(lái)訪問(wèn)name屬性,這就是默認(rèn)的規(guī)則。Java中提供了一套API用來(lái)訪問(wèn)某個(gè)屬性的getter/setter方法,通過(guò)這些API可以使你不需要了解這個(gè)規(guī)則,這些API存放于包java.beans中。
一般的做法是通過(guò)類Introspector來(lái)獲取某個(gè)對(duì)象的BeanInfo信息,然后通過(guò)BeanInfo來(lái)獲取屬性的描述器(PropertyDescriptor),通過(guò)這個(gè)屬性描述器就可以獲取某個(gè)屬性對(duì)應(yīng)的getter/setter方法,然后我們就可以通過(guò)反射機(jī)制來(lái)調(diào)用這些方法。下面我們來(lái)看一個(gè)例子,這個(gè)例子把某個(gè)對(duì)象的所有屬性名稱和值都打印出來(lái):
/* *Createdon2004-6-29 */ packagedemo; importjava.beans.BeanInfo; importjava.beans.Introspector; importjava.beans.PropertyDescriptor; publicclassIntrospectorDemo{ Stringname; publicstaticvoidmain(String[]args)throwsException{ IntrospectorDemodemo=newIntrospectorDemo(); demo.setName("WinterLau"); //如果不想把父類的屬性也列出來(lái)的話, //那getBeanInfo的第二個(gè)參數(shù)填寫(xiě)父類的信息 BeanInfobi=Introspector.getBeanInfo(demo.getClass(),Object.class); PropertyDescriptor[]props=bi.getPropertyDescriptors(); for(inti=0;i<props.length;i++){ System.out.println(props[i].getName()+"="+ props[i].getReadMethod().invoke(demo,null)); } } publicStringgetName(){ returnname; } publicvoidsetName(Stringname){ this.name=name; } } |
反射
相對(duì)而言,反射比內(nèi)省更容易理解一點(diǎn)。用一句比較白的話來(lái)概括,反射就是讓你可以通過(guò)名稱來(lái)得到對(duì)象(類,屬性,方法)的技術(shù)。例如我們可以通過(guò)類名來(lái)生成一個(gè)類的實(shí)例;知道了方法名,就可以調(diào)用這個(gè)方法;知道了屬性名就可以訪問(wèn)這個(gè)屬性的值,還是寫(xiě)兩個(gè)例子讓大家更直觀的了解反射的使用方法:
//通過(guò)類名來(lái)構(gòu)造一個(gè)類的實(shí)例 ClassClasscls_str=Class.forName("java.lang.String"); //上面這句很眼熟,因?yàn)槭褂眠^(guò)JDBC訪問(wèn)數(shù)據(jù)庫(kù)的人都用過(guò)J Objectstr=cls_str.newInstance(); //相當(dāng)于Stringstr=newString(); //通過(guò)方法名來(lái)調(diào)用一個(gè)方法 StringmethodName="length"; Methodm=cls_str.getMethod(methodName,null); System.out.println("lengthis"+m.invoke(str,null)); //相當(dāng)于System.out.println(str.length()); |
上面的兩個(gè)例子是比較常用方法?吹缴厦娴睦泳陀腥艘l(fā)問(wèn)了:為什么要這么麻煩呢?本來(lái)一條語(yǔ)句就完成的事情干嗎要整這么復(fù)雜?沒(méi)錯(cuò),在上面的例子中確實(shí)沒(méi)有必要這么麻煩。不過(guò)你想像這樣一個(gè)應(yīng)用程序,它支持動(dòng)態(tài)的功能擴(kuò)展,也就是說(shuō)程序不重新啟動(dòng)但是可以自動(dòng)加載新的功能,這個(gè)功能使用一個(gè)具體類來(lái)表示。首先我們必須為這些功能定義一個(gè)接口類,然后我們要求所有擴(kuò)展的功能類必須實(shí)現(xiàn)我指定的接口,這個(gè)規(guī)定了應(yīng)用程序和可擴(kuò)展功能之間的接口規(guī)則,但是怎么動(dòng)態(tài)加載呢?我們必須讓?xiě)?yīng)用程序知道要擴(kuò)展的功能類的類名,比如是test.Func1,當(dāng)我們把這個(gè)類名(字符串)告訴應(yīng)用程序后,它就可以使用我們第一個(gè)例子的方法來(lái)加載并啟用新的功能。這就是類的反射,請(qǐng)問(wèn)你有別的選擇嗎?
【Java的內(nèi)省與反射】相關(guān)文章:
JAVA認(rèn)證基礎(chǔ)知識(shí):基于反射機(jī)制的服務(wù)代理調(diào)用03-08
2016年JAVA認(rèn)證基礎(chǔ)知識(shí):基于反射機(jī)制的服務(wù)代理調(diào)用03-03
學(xué)習(xí)Java的技巧03-05
java習(xí)題及答案03-26
JAVA認(rèn)證簡(jiǎn)介03-19
關(guān)于Java的import03-16
Java入門(mén)基礎(chǔ)知識(shí):Java IO(輸入/輸出)03-07