Java基礎(chǔ)——反射

反射 框架設(shè)計(jì)的靈魂

Java中的反射顧名思義就是將類的各個(gè)組成部分封裝為其他對(duì)象鳄哭。使用這些封裝后的對(duì)象可以進(jìn)行一些操作攘乒。
對(duì)于反射機(jī)制义屏,我們可以說(shuō)反射就是框架設(shè)計(jì)的靈魂。很多框架內(nèi)部的機(jī)制都是反射溃蔫。
使用反射的好處就是:

  • 可以在程序運(yùn)行過(guò)程中,操作這些對(duì)象
  • 可以解耦琳猫,提高程序的可擴(kuò)展性

Class

說(shuō)起反射我們必須說(shuō)一個(gè)重要的類那就是Class伟叛。這個(gè)類代表了Java編譯后的字節(jié)碼對(duì)象。字節(jié)碼對(duì)象包含了定義類時(shí)所指定的全部的成員變量脐嫂、方法等屬性统刮。

Java執(zhí)行的三個(gè)階段

Java代碼的三個(gè)階段.jpg

Java的執(zhí)行過(guò)程是:我將Java代碼的執(zhí)行階段分為3個(gè)階段紊遵。分別是Source源代碼階段、Class類對(duì)象階段侥蒙、Runtime運(yùn)行時(shí)階段

  • Source源代碼階段:在這個(gè)階段中暗膜,Java會(huì)將源代碼編譯為字節(jié)碼文件,也就是我們平時(shí)見(jiàn)到的.class文件辉哥。
  • Class類對(duì)象階段:在這個(gè)階段中桦山,當(dāng)我們使用對(duì)應(yīng)的對(duì)象時(shí),類加載器ClassLoader就會(huì)將字節(jié)碼文件對(duì)象加載進(jìn)內(nèi)存醋旦。Class對(duì)象中封裝了源代碼中成員變量恒水、構(gòu)造方法、成員方法饲齐。
  • Runtime運(yùn)行時(shí)階段:在這個(gè)階段中在使用對(duì)應(yīng)的類對(duì)象的時(shí)候钉凌,JVM會(huì)將對(duì)應(yīng)的字節(jié)碼文件也就是我們前面說(shuō)過(guò)的Class對(duì)象加載進(jìn)內(nèi)存,這樣我們就能使用定義好的類和對(duì)象了捂人。

Class對(duì)象的方式

  1. Class.from("全類名") 將字節(jié)碼文件加載進(jìn)內(nèi)存御雕,返回一個(gè)class對(duì)象
  • 一般多用于配置文件,將類名定義在配置文件中滥搭,讀取配置文件酸纲,加載類
  1. 類名.class 通過(guò)類名的屬性class獲取 class對(duì)象
  • 多用于參數(shù)的傳遞
  1. 對(duì)象.getClass():getClass()方法定義在超類Object中

結(jié)論:同一個(gè)字節(jié)碼(*.class)在一次程序運(yùn)行過(guò)程中,只會(huì)被加載一次瑟匆,不論通過(guò)哪一種方式獲取的class對(duì)象都是同一個(gè)

Class對(duì)象功能

我們剛才說(shuō)了通過(guò)Class對(duì)象我們可以操作對(duì)象的屬性闽坡,那么我們?cè)趺传@取對(duì)象的屬性呢

獲取成員變量

  • Field[] getFields():獲取所有public修飾的成員變量 返回一個(gè)Field數(shù)組
  • Field getField(String name) 獲取指定名稱的public 修飾的變量

使用getFields只能獲取Public修飾的成員變量

  • Field[] getDeclaredFields() 獲取所有的成員變量,不考慮修飾符
  • Field getDeclaredField(String name) 獲取指定名稱的成員變量 不考慮修飾符

獲取構(gòu)造方法

  • Constructor<?>[] getConstructors() 獲取構(gòu)造方法的對(duì)象數(shù)組 public修飾
  • Constructor getConstructor(類<?>...parameterTypes)獲取指定參數(shù)的構(gòu)造方法 public修飾
  • Constructor getDeclaredConstructor(類<?>...parameterTypes) 獲取構(gòu)造方法對(duì)象 不考慮修飾符
  • Constructor[] getDeclaredConstructor() 獲取構(gòu)造方法的對(duì)象數(shù)組 不考慮修飾符

獲取成員方法

  • Method[] getMethods() 獲取成員方法數(shù)組 public修飾

getMethods不僅僅會(huì)獲取類的成員方法愁溜,還會(huì)獲取父類的方法

  • Method getMethod(String name,類<?>...parameterTypes) 獲取指定參數(shù)和類型的成員方法
  • Method[] getDeclareMethods 獲取成員方法數(shù)組 不考慮修飾符
  • Method getDeclareMethod(String name,類<?>....parameterTypes) 獲取指定參數(shù)的成員方法 不考慮修飾符

獲取全類名

  • String getName() 獲取class對(duì)象的全類名

Field成員變量

我們獲取了Field成員變量后可以通過(guò)Field設(shè)置對(duì)應(yīng)的成員變量的值
1 設(shè)置值
* void set(Object obj,Object value)
2 獲取值
* get(Object obj)
3 忽略訪問(wèn)權(quán)限修飾符的安全檢查
* setAccessible(true) 暴力反射

Constructor 構(gòu)造方法

通過(guò)Constructor構(gòu)造方法對(duì)象疾嗅。

  • T newInstance(Object...initargs) 創(chuàng)建對(duì)象
  • 如果使用空參數(shù)構(gòu)造方法的創(chuàng)建對(duì)象,操作可以簡(jiǎn)化 Class對(duì)象的newInstance方法
     Person person2 = (Person) cla.newInstance();
            System.out.println(person2);

如果構(gòu)造器是private修飾的冕象,我們也可以調(diào)用construct的setAccessible來(lái)進(jìn)行暴力反射
constructor.setAccessible(true) //暴力反射
暴力反射的前提必須使用declare的方法

Method方法對(duì)象

  • 執(zhí)行方法
    • Object invoke(Object obj,Object...args)
  • 獲取方法名稱
    • String getName獲取方法名
      普通的Method打印的是方法的全名(包名.類名.方法名)
      而getName獲取的方法名就是方法的名稱

學(xué)習(xí)了這么多代承,我們來(lái)實(shí)現(xiàn)一個(gè)案例來(lái)看一下反射的使用

案例

  • 需求:寫一個(gè)小框架,在不改變?nèi)魏晤惖那闆r下渐扮,執(zhí)行類中的任意方法
  • 步驟:
  1. 將需要?jiǎng)?chuàng)建的類的全類名和要執(zhí)行的方法定義在配置文件中
  2. 在程序中加載讀取配置文件
  3. 使用反射技術(shù)來(lái)加載類文件進(jìn)內(nèi)存
  4. 創(chuàng)建對(duì)象
  5. 執(zhí)行方法
  • 定義一個(gè)配置文件 pro.properties
className=com.probuing.bean.Student
methodName=study
  • 創(chuàng)建要執(zhí)行的實(shí)體類對(duì)象 Student.java
public class Student {
    public void study() {
        System.out.println("this is student is studing");
    }
}
  • 創(chuàng)建執(zhí)行框架
public class ReflectFrame {
    public static void main(String[] args) {
        try {
            //加載配置文件
            Properties pro = new Properties();
            //獲取類加載器论悴,獲取配置文件路徑
            ClassLoader classLoader = ReflectFrame.class.getClassLoader();
            InputStream resourceAsStream = classLoader.getResourceAsStream("pro.properties");
            //加載配置文件,轉(zhuǎn)換為一個(gè)集合
            pro.load(resourceAsStream);
            //獲取配置文件中定義的數(shù)據(jù)
            String className = pro.getProperty("className");
            String methodName = pro.getProperty("methodName");
            //加載指定的類class進(jìn)內(nèi)存
            Class<?> cla = Class.forName(className);
            //創(chuàng)建對(duì)象
            Student student = (Student) cla.newInstance();
            //獲取方法對(duì)象
            Method method = cla.getMethod(methodName);
            //執(zhí)行方法
            method.invoke(student);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末墓律,一起剝皮案震驚了整個(gè)濱河市意荤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌只锻,老刑警劉巖玖像,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡捐寥,警方通過(guò)查閱死者的電腦和手機(jī)笤昨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)握恳,“玉大人瞒窒,你說(shuō)我怎么就攤上這事∠缤荩” “怎么了崇裁?”我有些...
    開(kāi)封第一講書人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)束昵。 經(jīng)常有香客問(wèn)我拔稳,道長(zhǎng),這世上最難降的妖魔是什么锹雏? 我笑而不...
    開(kāi)封第一講書人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任巴比,我火速辦了婚禮,結(jié)果婚禮上礁遵,老公的妹妹穿的比我還像新娘轻绞。我一直安慰自己,他們只是感情好佣耐,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布政勃。 她就那樣靜靜地躺著,像睡著了一般兼砖。 火紅的嫁衣襯著肌膚如雪奸远。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,772評(píng)論 1 290
  • 那天掖鱼,我揣著相機(jī)與錄音然走,去河邊找鬼援制。 笑死戏挡,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的晨仑。 我是一名探鬼主播褐墅,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼洪己!你這毒婦竟也來(lái)了妥凳?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤答捕,失蹤者是張志新(化名)和其女友劉穎逝钥,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體拱镐,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡艘款,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年持际,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片哗咆。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蜘欲,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出晌柬,到底是詐尸還是另有隱情姥份,我是刑警寧澤,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布年碘,位于F島的核電站澈歉,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏盛泡。R本人自食惡果不足惜闷祥,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望傲诵。 院中可真熱鬧凯砍,春花似錦、人聲如沸拴竹。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)栓拜。三九已至座泳,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間幕与,已是汗流浹背挑势。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留啦鸣,地道東北人潮饱。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像诫给,于是被迫代替她去往敵國(guó)和親香拉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

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

  • 一中狂、類的加載 (一) 定義及過(guò)程: 當(dāng)程序需要使用某個(gè)類的時(shí)候凫碌,如果這個(gè)類還沒(méi)有被加載到內(nèi)存中,則系統(tǒng)會(huì)通過(guò)加載胃榕、...
    VictorBXv閱讀 318評(píng)論 0 2
  • 夯實(shí) Java 基礎(chǔ) - 反射 自嵌套 Fragment 懶加載文章至今已經(jīng)已經(jīng)一個(gè)星期過(guò)去了盛险,說(shuō)實(shí)話最近對(duì)于學(xué)習(xí)...
    醒著的碼者閱讀 720評(píng)論 2 2
  • 反射注解動(dòng)態(tài)代理相關(guān)閱讀 Java基礎(chǔ):類加載器 Java基礎(chǔ):反射 Java基礎(chǔ):注解 Java基礎(chǔ):動(dòng)態(tài)代理 ...
    JackChen1024閱讀 921評(píng)論 3 27
  • 深入理解Class對(duì)象 RRTI的概念以及Class對(duì)象作用 認(rèn)識(shí)Class對(duì)象之前,先來(lái)了解一個(gè)概念,RTTI(...
    架構(gòu)師springboot閱讀 1,557評(píng)論 0 3
  • JAVA反射機(jī)制是在運(yùn)行狀態(tài)中苦掘,對(duì)于任意一個(gè)類泉褐,都能夠知道這個(gè)類的所有屬性和方法;對(duì)于任意一個(gè)對(duì)象鸟蜡,都能夠調(diào)用它的...
    陳晨_Fly閱讀 957評(píng)論 0 20