Java 反射機(jī)制原理與用法詳解
本文實(shí)例講述了Java 反射機(jī)制原理與用法。分享給大家供大家參考,具體如下:
Java 反射機(jī)制
Reflection(反射)是被視為動(dòng)態(tài)語(yǔ)言的關(guān)鍵,反射機(jī)制允許程序在執(zhí)行期借助于Reflection
API取得任何類的內(nèi)部信息,并能直接操作任意對(duì)象的內(nèi)部屬性及方法。
Java反射機(jī)制提供的功能
- 在運(yùn)行時(shí)判斷任意一個(gè)對(duì)象所屬的類
- 在運(yùn)行時(shí)構(gòu)造任意一個(gè)類的對(duì)象
- 在運(yùn)行時(shí)判斷任意一個(gè)類所具有的成員變量和方法
- 在運(yùn)行時(shí)調(diào)用任意一個(gè)對(duì)象的成員變量和方法
- 生成動(dòng)態(tài)代理
反射相關(guān)的主要API:
- java.lang.Class:代表一個(gè)類
- java.lang.reflect.Method:代表類的方法
- java.lang.reflect.Field:代表類的成員變量
- java.lang.reflect.Constructor:代表類的構(gòu)造方法
Class類
- 對(duì)照鏡子后可以得到的信息:某個(gè)類的屬性、方法和構(gòu)造器、某個(gè)類到底實(shí)現(xiàn)了哪些接口。對(duì)于每個(gè)類而言,JRE 都為其保留一個(gè)不變的 Class類型的對(duì)象。一個(gè) Class對(duì)象包含了特定某個(gè)類的有關(guān)信息。
- Class本身也是一個(gè)類
- Class對(duì)象只能由系統(tǒng)建立對(duì)象
- 一個(gè)類在JVM 中只會(huì)有一個(gè)Class實(shí)例
- 一個(gè)Class對(duì)象對(duì)應(yīng)的是一個(gè)加載到JVM中的一個(gè).class文件
- 每個(gè)類的實(shí)例都會(huì)記得自己是由哪個(gè)Class 實(shí)例所生成
- 通過(guò)Class可以完整地得到一個(gè)類中的完整結(jié)構(gòu)
實(shí)例化Class類對(duì)象
1、前提:若已知具體的類,通過(guò)類的class屬性獲取,該方法最為安全可靠,程序性能最高
實(shí)例:
Class clazz = String.class;
2、前提:已知某個(gè)類的實(shí)例,調(diào)用該實(shí)例的getClass()方法獲取Class對(duì)象
實(shí)例:
Class clazz ="www.atguigu.com".getClass();
3、前提:已知一個(gè)類的全類名,且該類在類路徑下,可通過(guò)Class類的靜態(tài)方法forName()獲取,可能拋出
ClassNotFoundException
實(shí)例:
Classclazz= Class.forName("java.lang.String");
4、其他方式(不做要求)
ClassLoader cl =this.getClass().getClassLoader(); Classclazz4 = cl.loadClass("類的全類名");
創(chuàng)建類對(duì)象并獲取類的完整結(jié)構(gòu)
1.創(chuàng)建類的對(duì)象:調(diào)用Class對(duì)象的newInstance()
方法
要求:
1)類必須有一個(gè)無(wú)參數(shù)的構(gòu)造器。
2)類的構(gòu)造器的訪問(wèn)權(quán)限需要足夠。
難道沒(méi)有無(wú)參的構(gòu)造器就不能創(chuàng)建對(duì)象了嗎?
不是!只要在操作的時(shí)候明確的調(diào)用類中的構(gòu)造方法,并將參數(shù)傳遞進(jìn)去之后,才可以實(shí)例化操作。步驟如下:
1)通過(guò)Class類的getDeclaredConstructor(Class …parameterTypes)取得本類的指定形參類型的構(gòu)造器
2)向構(gòu)造器的形參中傳遞一個(gè)對(duì)象數(shù)組進(jìn)去,里面包含了構(gòu)造器中所需的各個(gè)參數(shù)。
//1.根據(jù)全類名獲取對(duì)應(yīng)的Class對(duì)象 String name = "atguigu.java.Person"; Class clazz = null; clazz = Class.forName(name); //2.調(diào)用指定參數(shù)結(jié)構(gòu)的構(gòu)造器,生成Constructor的實(shí)例 Constructor con = clazz.getConstructor(String.class,Integer.class); //3.通過(guò)Constructor的實(shí)例創(chuàng)建對(duì)應(yīng)類的對(duì)象,并初始化類屬性 Person p2 = (Person) con.newInstance("Peter",20); System.out.println(p2);
通過(guò)反射調(diào)用類的完整結(jié)構(gòu)
使用反射可以取得:
1.實(shí)現(xiàn)的全部接口
public Class
通過(guò)反射調(diào)用類中的指定方法、指定屬性
1.調(diào)用指定方法
通過(guò)反射,調(diào)用類中的方法,通過(guò)Method類完成。步驟:
1.通過(guò)Class類的getMethod(String name,Class…parameterTypes)
方法取得一個(gè)Method對(duì)象,并設(shè)置此方法操作時(shí)所需要的參數(shù)類型。
2.之后使用Object invoke(Object obj, Object[] args)
進(jìn)行調(diào)用,并向方法中傳遞要設(shè)置的obj對(duì)象的參數(shù)信息。
Object invoke(Object obj, Object … args)
說(shuō)明:
1.Object 對(duì)應(yīng)原方法的返回值,若原方法無(wú)返回值,此時(shí)返回null
2.若原方法若為靜態(tài)方法,此時(shí)形參Objectobj可為null
3.若原方法形參列表為空,則Object[]args為null
4.若原方法聲明為private,則需要在調(diào)用此invoke()方法前,顯式調(diào)用方法對(duì)象的 setAccessible(true)方法,將可訪問(wèn)private的方法。
2.調(diào)用指定屬性
在反射機(jī)制中,可以直接通過(guò)Field類操作類中的屬性,通過(guò)Field類提供的set()和get()方法就可以完成設(shè)置和取得屬性內(nèi)容的操作。
public Field getField(Stringname)
返回此Class對(duì)象表示的類或接口的指定的public的Field。
public Field getDeclaredField(Stringname)
返回此Class對(duì)象表示的類或接口的指定的Field。
在Field中:
public Object get(Object obj)
取得指定對(duì)象obj上此Field的屬性內(nèi)容
public void set(Object obj,Objectvalue)
設(shè)置指定對(duì)象obj上此Field的屬性內(nèi)容
注:在類中屬性都設(shè)置為private的前提下,在使用set()和get()方法時(shí),首先要使用Field類中的setAccessible(true)方法將需要操作的屬性設(shè)置為可以被外部訪問(wèn)。
public void setAccessible(true)
訪問(wèn)私有屬性時(shí),讓這個(gè)屬性可見(jiàn)。
Java動(dòng)態(tài)代理
1、動(dòng)態(tài)代理是指客戶通過(guò)代理類來(lái)調(diào)用其它對(duì)象的方法,并且是在程序運(yùn)行時(shí)根據(jù)需要?jiǎng)討B(tài)創(chuàng)建目標(biāo)類的代理對(duì)象。
2、動(dòng)態(tài)代理使用場(chǎng)合:
- 調(diào)試
- 遠(yuǎn)程方法調(diào)用
3、代理設(shè)計(jì)模式的原理:
- 使用一個(gè)代理將對(duì)象包裝起來(lái), 然后用該代理對(duì)象取代原始對(duì)象. 任何對(duì)原始對(duì)象的調(diào)用都要通過(guò)代理. 代理對(duì)象決定是否以及何時(shí)將方法調(diào)用轉(zhuǎn)到原始對(duì)象上
4、Proxy :專門(mén)完成代理的操作類,是所有動(dòng)態(tài)代理類的父類。通過(guò)此類為一個(gè)或多個(gè)接口動(dòng)態(tài)地生成實(shí)現(xiàn)類。
5、提供用于創(chuàng)建動(dòng)態(tài)代理類和動(dòng)態(tài)代理對(duì)象的靜態(tài)方法
static Class
更多java相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Java面向?qū)ο蟪绦蛟O(shè)計(jì)入門(mén)與進(jìn)階教程》、《Java數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Java操作DOM節(jié)點(diǎn)技巧總結(jié)》、《Java文件與目錄操作技巧匯總》和《Java緩存操作技巧匯總》
希望本文所述對(duì)大家java程序設(shè)計(jì)有所幫助。
相關(guān)文章
Java中通過(guò)sftp協(xié)議實(shí)現(xiàn)上傳下載的示例代碼
在java開(kāi)發(fā)中遇到需要將linux系統(tǒng)中指定目錄下的文件下載到windows本地的需求,本文就來(lái)介紹Java中通過(guò)sftp協(xié)議實(shí)現(xiàn)上傳下載,具有一定的參考價(jià)值,感興趣的可以了解一下2024-06-06Spring boot2.x中集成H2數(shù)據(jù)庫(kù)代碼實(shí)例
這篇文章主要介紹了Spring boot2.x中集成H2數(shù)據(jù)庫(kù)代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12Kafka單節(jié)點(diǎn)偽分布式集群搭建實(shí)現(xiàn)過(guò)程詳解
這篇文章主要介紹了Kafka單節(jié)點(diǎn)偽分布式集群搭建實(shí)現(xiàn)過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11淺談在springboot中使用定時(shí)任務(wù)的方式
今天給大家?guī)?lái)的是關(guān)于Java的相關(guān)知識(shí),文章圍繞著在springboot中使用定時(shí)任務(wù)的方式展開(kāi),文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下2021-06-06解決mybatis使用char類型字段查詢oracle數(shù)據(jù)庫(kù)時(shí)結(jié)果返回null問(wèn)題
這篇文章主要介紹了mybatis使用char類型字段查詢oracle數(shù)據(jù)庫(kù)時(shí)結(jié)果返回null問(wèn)題的解決方法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-06-06java開(kāi)發(fā)之基于Validator接口的SpringMVC數(shù)據(jù)校驗(yàn)方式
這篇文章主要介紹了java開(kāi)發(fā)之基于Validator接口的SpringMVC數(shù)據(jù)校驗(yàn)方式,文中附含詳細(xì)示例代碼,有需要的朋友可以借鑒參考下2021-09-09Java多線程下解決資源競(jìng)爭(zhēng)的7種方法詳解
這篇文章主要介紹了Java多線程下解決資源競(jìng)爭(zhēng)的7種方法詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08ThreadLocal線程在Java框架中的應(yīng)用及原理深入理解
這篇文章主要介紹了ThreadLocal在Java框架中的應(yīng)用及原理深入理解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01