Java基础 反射
一、什么是反射?
? ? ? ? 反射是Java最經(jīng)常用到的基礎(chǔ)知識(shí),但是也是比較難理解的一點(diǎn)。今天就來好好說說他。
????? ?根據(jù)反射的普遍解釋就是:在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ì)象的方法的功能來自于Java 語言的反射(Reflection)機(jī)制
????????簡言之,反射(Reflection)就是在Java運(yùn)行時(shí),動(dòng)態(tài)獲取類(class)的信息以及動(dòng)態(tài)調(diào)用對(duì)象(Object)的方法的功能。
????? ?反射的優(yōu)缺點(diǎn):
????? ? 優(yōu)點(diǎn)就是動(dòng)態(tài)創(chuàng)建對(duì)象和編譯,靈活性高。
????? ? 反射的缺點(diǎn)就是對(duì)性能有些影響。(缺點(diǎn)實(shí)際上由于現(xiàn)在JVM的性能提高,和在開發(fā)時(shí)有一些編輯是可控的可以降低對(duì)性能的影響)
二、反射的主要用途
????????? ?spring管理著bean組件,簡單來說省去了龐雜的new來調(diào)取對(duì)象。這就是我們最長接觸到的反射機(jī)制。原來EJB就是通過new這種方式來調(diào)用對(duì)象:
????????? ?而spring運(yùn)用反射則將原來的這種方式直接配置到一個(gè)配置文件中來避免ejb對(duì)象的頻繁調(diào)用和解耦。
????????????? ??
????????? ?可以從內(nèi)存角度去理解反射,也可以從我反射的定義去理解它。即當(dāng)我們平時(shí)“引入類的名稱->通過new實(shí)例化->取得實(shí)例化對(duì)象”的過程。使用反射就可以變成“實(shí)例化對(duì)象->getClass()方法->得到完整的類名稱”這樣的過程。
????????? ? 反射機(jī)制主要提供了4個(gè)功能:
????????????????? ? 1、在運(yùn)行時(shí)判斷任意一個(gè)對(duì)象所屬的類
????????????????? ? 2、在運(yùn)行時(shí)構(gòu)造任意一個(gè)類的對(duì)象
????????????????????3、在運(yùn)行時(shí)判斷任意一個(gè)類所具有的成員變量
????????????????? ? 4、在運(yùn)行時(shí)調(diào)用任意一個(gè)對(duì)象的方法
????????? ? Java反射機(jī)制常用到4個(gè)類:Class,Construct,Field,Method,
????????? ? 其中Construct,Field,Method是屬于Java.lang.refleact包下,releact包主要就是提供反射的API,Class類則獲取一個(gè)要操作的類的對(duì)象,該對(duì)象屬于java.lang.object包,該對(duì)象代表一個(gè)正在運(yùn)行的一個(gè)類或接口。下圖是jdk源碼,各類所在的位置:
二、反射的分析
? ? 首先,從內(nèi)存角度分析反射。這里引用個(gè)經(jīng)常出現(xiàn)的內(nèi)存資料圖片:
????????
????????由圖可知,運(yùn)行時(shí)JVM的內(nèi)存結(jié)構(gòu)。我們平時(shí)用IDE開發(fā)時(shí)候的.Java先編譯成.class文件,然后被類加載器加載到JVM中。然后被類加載器加載進(jìn)jvm的內(nèi)存中,此時(shí)類Object加載到方法區(qū)中,創(chuàng)建了Object類的class對(duì)象到堆中,注意這個(gè)不是new出來的對(duì)象,而是類的類型對(duì)象,每個(gè)類只有一個(gè)Class對(duì)象,作為方法區(qū)類的數(shù)據(jù)結(jié)構(gòu)的接口。jvm創(chuàng)建對(duì)象前,會(huì)先檢查類是否加載,尋找類對(duì)應(yīng)的Class對(duì)象,若加載好,則為你的對(duì)象分配內(nèi)存,初始化也就是new 。
反射是什么呢?當(dāng)我們的程序在運(yùn)行時(shí),需要?jiǎng)討B(tài)的加載一些類這些類可能之前用不到所以不用加載到j(luò)vm,而是在運(yùn)行時(shí)根據(jù)需要才加載,這樣的好處對(duì)于服務(wù)器來說不言而喻。 舉個(gè)例子我們的項(xiàng)目底層有時(shí)是用mysql,有時(shí)用oracle,需要?jiǎng)討B(tài)地根據(jù)實(shí)際情況加載驅(qū)動(dòng)類,這個(gè)時(shí)候反射就有用了。 假設(shè) com.java.dbtest.myqlConnection,com.java.dbtest.oracleConnection這兩個(gè)類我們要用,這時(shí)候我們的程序就寫得比較動(dòng)態(tài)化,通過Class tc = Class.forName("com.java.dbtest.TestConnection"); 通過類的全類名讓jvm在服務(wù)器中找到并加載這個(gè)類,而如果是oracle則傳入的參數(shù)就變成另一個(gè)了。這時(shí)候就可以看到反射的好處了,這個(gè)動(dòng)態(tài)性就體現(xiàn)出java的特性了! 舉多個(gè)例子,大家如果接觸過spring,會(huì)發(fā)現(xiàn)當(dāng)你配置各種各樣的bean時(shí),是以配置文件的形式配置的,你需要用到哪些bean就配哪些,spring容器就會(huì)根據(jù)你的需求去動(dòng)態(tài)加載,你的程序就能健壯地運(yùn)行。????????第二個(gè),就是從Java源碼,反射的定義這個(gè)角度去理解,這里需要用到的方式就不再介紹了,因?yàn)榫W(wǎng)上這個(gè)方式很多,下面就列出個(gè)小栗子:
內(nèi)存角度的分析這里引用了知乎,作者:老頑童周伯通?的觀點(diǎn)和講解。鏈接:https://www.zhihu.com/question/24304289/answer/147529485
總結(jié)
- 上一篇: Java基础 抽象类和接口的区别、eq
- 下一篇: Java基础 正则表达式 Patter