一、什么是反射:
反射的概念是由Smith在1982年首次提出的,主要是指程序可以訪問(wèn)、檢測(cè)和修改它本身狀態(tài)或行為的一種能力。這一概念的提出很快引發(fā)了計(jì)算機(jī)科學(xué)領(lǐng)域關(guān)于應(yīng)用反射性的研究。它首先被程序語(yǔ)言的設(shè)計(jì)領(lǐng)域所采用,并在Lisp和面向?qū)ο蠓矫嫒〉昧顺煽?jī)。其中LEAD/LEAD++ 、OpenC++ 、metaXa和OpenJava等就是基于反射機(jī)制的語(yǔ)言。最近,反射機(jī)制也被應(yīng)用到了視窗系統(tǒng)、操作系統(tǒng)和文件系統(tǒng)中。
反射本身并不是一個(gè)新概念,盡管計(jì)算機(jī)科學(xué)賦予了反射概念新的含義。在計(jì)算機(jī)科學(xué)領(lǐng)域,反射是指一類(lèi)應(yīng)用,它們能夠自描述和自控制。也就是說(shuō),這類(lèi)應(yīng)用通過(guò)采用某種機(jī)制來(lái)實(shí)現(xiàn)對(duì)自己行為的描述(self-representation)和監(jiān)測(cè)(examination),并能根據(jù)自身行為的狀態(tài)和結(jié)果,調(diào)整或修改應(yīng)用所描述行為的狀態(tài)和相關(guān)的語(yǔ)義。
二、什么是Java中的類(lèi)反射:
Reflection 是 Java 程序開(kāi)發(fā)語(yǔ)言的特征之一,它允許運(yùn)行中的 Java 程序?qū)ψ陨磉M(jìn)行檢查,或者說(shuō)“自審”,并能直接操作程序的內(nèi)部屬性和方法。Java 的這一能力在實(shí)際應(yīng)用中用得不是很多,但是在其它的程序設(shè)計(jì)語(yǔ)言中根本就不存在這一特性。例如,Pascal、C 或者 C++ 中就沒(méi)有辦法在程序中獲得函數(shù)定義相關(guān)的信息。
Reflection 是 Java 被視為動(dòng)態(tài)(或準(zhǔn)動(dòng)態(tài))語(yǔ)言的關(guān)鍵,允許程序于執(zhí)行期 Reflection APIs 取得任何已知名稱(chēng)之 class 的內(nèi)部信息,包括 package、type parameters、superclass、implemented interfaces、inner classes, outer class, fields、constructors、methods、modifiers,並可于執(zhí)行期生成instances、變更 fields 內(nèi)容或喚起 methods。
三、Java類(lèi)反射中所必須的類(lèi):
Java的類(lèi)反射所需要的類(lèi)并不多,它們分別是:Field、Constructor、Method、Class、Object,下面我將對(duì)這些類(lèi)做一個(gè)簡(jiǎn)單的說(shuō)明。
Field類(lèi):提供有關(guān)類(lèi)或接口的屬性的信息,以及對(duì)它的動(dòng)態(tài)訪問(wèn)權(quán)限。反射的字段可能是一個(gè)類(lèi)(靜態(tài))屬性或?qū)嵗龑傩?,?jiǎn)單的理解可以把它看成一個(gè)封裝反射類(lèi)的屬性的類(lèi)。
Constructor類(lèi):提供關(guān)于類(lèi)的單個(gè)構(gòu)造方法的信息以及對(duì)它的訪問(wèn)權(quán)限。這個(gè)類(lèi)和Field類(lèi)不同,F(xiàn)ield類(lèi)封裝了反射類(lèi)的屬性,而Constructor類(lèi)則封裝了反射類(lèi)的構(gòu)造方法。
Method類(lèi):提供關(guān)于類(lèi)或接口上單獨(dú)某個(gè)方法的信息。所反映的方法可能是類(lèi)方法或?qū)嵗椒?包括抽象方法)。 這個(gè)類(lèi)不難理解,它是用來(lái)封裝反射類(lèi)方法的一個(gè)類(lèi)。
Class類(lèi):類(lèi)的實(shí)例表示正在運(yùn)行的 Java 應(yīng)用程序中的類(lèi)和接口。枚舉是一種類(lèi),注釋是一種接口。每個(gè)數(shù)組屬于被映射為 Class 對(duì)象的一個(gè)類(lèi),所有具有相同元素類(lèi)型和維數(shù)的數(shù)組都共享該 Class 對(duì)象。
Object類(lèi):每個(gè)類(lèi)都使用 Object 作為超類(lèi)。所有對(duì)象(包括數(shù)組)都實(shí)現(xiàn)這個(gè)類(lèi)的方法。
四、Java的反射類(lèi)能做什么:
看完上面的這么多我想你已經(jīng)不耐煩了,你以為我在浪費(fèi)你的時(shí)間,那么好吧!下面我們就用一些簡(jiǎn)單的小例子來(lái)說(shuō)明它。
首先我們來(lái)看一下通過(guò)Java的反射機(jī)制我們能得到些什么。
首先我們來(lái)寫(xiě)一個(gè)類(lèi):
你可能被我這個(gè)類(lèi)弄糊涂了,你看不出我要做什么,那就不要看這個(gè)類(lèi)了,這個(gè)類(lèi)是用來(lái)測(cè)試的,你知道知道它繼承了Object類(lèi),有一個(gè)接口是ActionListener,兩個(gè)屬性int和Integer,兩個(gè)構(gòu)造方法和兩個(gè)方法,這就足夠了。
下面我們把A這個(gè)類(lèi)作為一個(gè)反射類(lèi),來(lái)過(guò)去A類(lèi)中的一些信息,首先我們先來(lái)過(guò)去一下反射類(lèi)中的屬性和屬性值。
這里用到了兩個(gè)方法,getFields()、getDeclaredFields(),它們分別是用來(lái)獲取反射類(lèi)中所有公有屬性和反射類(lèi)中所有的屬性的方法。另外還有g(shù)etField(String)和getDeclaredField(String)方法都是用來(lái)過(guò)去反射類(lèi)中指定的屬性的方法,要注意的是getField方法只能取到反射類(lèi)中公有的屬性,而getDeclaredField方法都能取到。
這里還用到了Field 類(lèi)的setAccessible方法,它是用來(lái)設(shè)置是否有權(quán)限訪問(wèn)反射類(lèi)中的私有屬性的,只有設(shè)置為true時(shí)才可以訪問(wèn),默認(rèn)為false。另外 Field類(lèi)還有set(Object AttributeName,Object value)方法,可以改變指定屬性的值。
下面我們來(lái)看一下如何獲取反射類(lèi)中的構(gòu)造方法
這個(gè)例子很簡(jiǎn)單,只是用getConstructors()方法獲取了反射類(lèi)的構(gòu)造方法的集合,并用Constructor類(lèi)的getParameterTypes()獲取該構(gòu)造方法的參數(shù)。
下面我們?cè)賮?lái)獲取一下反射類(lèi)的父類(lèi)(超類(lèi))和接口
這個(gè)例子也很簡(jiǎn)單,只是用Class類(lèi)的getInterfaces()方法獲取反射類(lèi)的所有接口,由于接口可以有多個(gè),所以它返回一個(gè) Class數(shù)組。用getSuperclass()方法來(lái)獲取反射類(lèi)的父類(lèi)(超類(lèi)),由于一個(gè)類(lèi)只能繼承自一個(gè)類(lèi),所以它返回一個(gè)Class對(duì)象。
下面我們來(lái)獲取一下反射類(lèi)的方法
這個(gè)例子并不難,它只是獲得了反射類(lèi)的所有方法,包括繼承自它父類(lèi)的方法。然后獲取方法的返回類(lèi)型、方法名和方法參數(shù)。
接下來(lái)讓我們回過(guò)頭來(lái)想一想,我們獲取了反射類(lèi)的屬性、構(gòu)造方法、父類(lèi)、接口和方法,可這些東西能幫我們做些什么呢!!
下面我寫(xiě)一個(gè)比較完整的小例子,來(lái)說(shuō)明Java的反射類(lèi)能做些什么吧!!
這是我在工作中寫(xiě)的一個(gè)實(shí)現(xiàn)Java在運(yùn)行時(shí)加載指定的類(lèi),并調(diào)用指定方法的一個(gè)小例子。這里沒(méi)有main方法,你可以自己寫(xiě)一個(gè)。
Load方法接收的五個(gè)參數(shù)分別是,Java的類(lèi)名,方法名,參數(shù)的類(lèi)型和參數(shù)的值。
結(jié)束語(yǔ):
Java語(yǔ)言反射提供一種動(dòng)態(tài)鏈接程序組件的多功能方法。它允許程序創(chuàng)建和控制任何類(lèi)的對(duì)象,無(wú)需提前硬編碼目標(biāo)類(lèi)。這些特性使得反射特別適用于創(chuàng)建以非常普通的方式與對(duì)象協(xié)作的庫(kù)。Java reflection 非常有用,它使類(lèi)和數(shù)據(jù)結(jié)構(gòu)能按名稱(chēng)動(dòng)態(tài)檢索相關(guān)信息,并允許在運(yùn)行著的程序中操作這些信息。Java 的這一特性非常強(qiáng)大,并且是其它一些常用語(yǔ)言,如 C、C++、Fortran 或者 Pascal 等都不具備的。
但反射有兩個(gè)缺點(diǎn)。第一個(gè)是性能問(wèn)題。用于字段和方法接入時(shí)反射要遠(yuǎn)慢于直接代碼。性能問(wèn)題的程度取決于程序中是如何使用反射的。如果它作為程序運(yùn)行中相對(duì)很少涉及的部分,緩慢的性能將不會(huì)是一個(gè)問(wèn)題。即使測(cè)試中最壞情況下的計(jì)時(shí)圖顯示的反射操作只耗用幾微秒。僅反射在性能關(guān)鍵的應(yīng)用的核心邏輯中使用時(shí)性能問(wèn)題才變得至關(guān)重要。
以上就是北大青鳥(niǎo)長(zhǎng)沙麓谷校區(qū)Java培訓(xùn)機(jī)構(gòu)小編介紹的“Java培訓(xùn)教程:Java反射機(jī)制教程”的內(nèi)容,希望對(duì)大家有幫助,如有疑問(wèn),請(qǐng)?jiān)诰€咨詢(xún),有專(zhuān)業(yè)老師隨時(shí)為你服務(wù)。
相關(guān)文章
零基礎(chǔ)怎么自學(xué)Java,完整版Java學(xué)習(xí)路線圖
你還在糾結(jié)學(xué)Java,是自學(xué)還是去培訓(xùn)班嗎
一個(gè)標(biāo)準(zhǔn)的Java程序員如何進(jìn)階?
Java學(xué)習(xí)路線清單,快速進(jìn)階Java
Java編程初學(xué)者要如何進(jìn)階
Java培訓(xùn) Java培訓(xùn)教程 Java教程