Java學(xué)習(xí)總結(jié)-反射

反射經(jīng)常聽(tīng)到這個(gè)詞械媒,但是總是不理解這個(gè)意思。今天便來(lái)理解一下反射這個(gè)概念评汰,為什么說(shuō)在框架設(shè)計(jì)中纷捞,反射用到的比較多。本文記錄一下學(xué)習(xí)反射方面的知識(shí)點(diǎn)被去。

反射概念

JAVA反射機(jī)制是在運(yùn)行狀態(tài)中主儡,對(duì)于任意一個(gè)類(lèi),都能夠知道這個(gè)類(lèi)的所有屬性和方法惨缆;對(duì)于任意一個(gè)對(duì)象糜值,都能夠調(diào)用它的任意一個(gè)方法和屬性;這種動(dòng)態(tài)獲取的信息以及動(dòng)態(tài)調(diào)用對(duì)象的方法的功能稱(chēng)為java語(yǔ)言的反射機(jī)制坯墨。概念比較精確寂汇、抽象但是不便于理解。譬如我們存在一個(gè)類(lèi)捣染,它的相關(guān)屬性骄瓣、方法、構(gòu)造器都是 private 類(lèi)型的耍攘,對(duì)于這樣一個(gè)類(lèi)榕栏,我們不能通過(guò) new 的方式來(lái)創(chuàng)建一個(gè)它的對(duì)象,更不能通過(guò)平常使用方法屬性的方式來(lái)調(diào)用這個(gè)類(lèi)的屬性少漆、方法臼膏,甚至來(lái)創(chuàng)建它的對(duì)象,但是通過(guò)反射這種方式卻可以生成它的對(duì)象以及調(diào)用它的屬性示损、方法渗磅。

Class

Class 與 class 有著本質(zhì)的區(qū)別。小寫(xiě)的 class 是 Java 中的關(guān)鍵字,而大寫(xiě)的 Class 則是類(lèi)始鱼。

public final class Class<T> implements java.io.Serializable,
                              GenericDeclaration,
                              Type,
                              AnnotatedElement {
}

在 Java 的世界里仔掸,一切皆是對(duì)象,在 Java 中存在兩種對(duì)象医清,一種是 new 產(chǎn)生的對(duì)象另一種則是 Class 對(duì)象起暮。一般的對(duì)象,我們可以通過(guò) new 關(guān)鍵字來(lái)產(chǎn)生会烙,而 Class 對(duì)象則不可以负懦,因?yàn)樗?JVM 生成用來(lái)保存對(duì)應(yīng)類(lèi)的信息的。也就是說(shuō)柏腻,如:當(dāng)我們定義了一個(gè)類(lèi) Person 時(shí)纸厉,編譯成功后,將會(huì)生成一個(gè) Person.class 字節(jié)碼五嫂,這個(gè)時(shí)候編譯器同時(shí)為我們從創(chuàng)建了一個(gè) Class 對(duì)象并將它保存在 Person.class 文件中颗品。也就是說(shuō):Person.java 編譯成 Person.class 后將會(huì)產(chǎn)生一個(gè)對(duì)應(yīng)的Class 對(duì)象。

Class 對(duì)象獲取

一般情況下沃缘,一個(gè)實(shí)例對(duì)象對(duì)應(yīng)的 Class 對(duì)象有以下三種方式獲惹唷:

1、通過(guò)實(shí)例變量的 getClass 方法:

Person person = new Person();
Class personClass = person.getClass();
System.out.println("class1: " + personClass);

2槐臀、直接給出對(duì)象類(lèi)文件的.class:

Class personClass1=Person.class;
System.out.println("class2: " + personClass1);

如果不能通過(guò) new 關(guān)鍵字來(lái)創(chuàng)建對(duì)象的話锄蹂,我們也可以通過(guò)第三種方式來(lái)獲取:

3峰档、通過(guò)類(lèi)Class的靜態(tài)方法forName():

try {
          Class personClass2 = Class.forName("reflect.Person");
          System.out.println("class3: " + personClass2);
      } catch (ClassNotFoundException e) {
          e.printStackTrace();
      }

打印結(jié)果如下:

class1: class reflect.Person
class2: class reflect.Person
class3: class reflect.Person

Class 使用

JAVA反射機(jī)制是在運(yùn)行狀態(tài)中败匹,對(duì)于任意一個(gè)類(lèi),都能夠知道這個(gè)類(lèi)的所有屬性和方法讥巡;對(duì)于任意一個(gè)對(duì)象掀亩,都能夠調(diào)用它的任意一個(gè)方法和屬性;這種動(dòng)態(tài)獲取的信息以及動(dòng)態(tài)調(diào)用對(duì)象的方法的功能稱(chēng)為java語(yǔ)言的反射機(jī)制欢顷。

1槽棍、CLASS 名稱(chēng)獲取
對(duì)于 name 的獲取,Class 類(lèi)提供了三種方法:

Class.getName();
Class.getSimpleName();
Class.getCanonicalName();

那么這三種方式有何區(qū)別抬驴?通過(guò)具體的實(shí)例還說(shuō)明炼七。

首先我們得創(chuàng)建一個(gè)類(lèi) Person.java

package reflect;
public class Person {
    private int age;
    private String name;
    public Person() {
    }
    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

然后分別獲取它的 Class 名稱(chēng):

      //getName()方式
      Person person = new Person();
      Class personClass = person.getClass();
      System.out.println("class1: " + personClass.getName());
 //getSimpleName()方式
      Class personClass1=Person.class;
      System.out.println("class2: " + personClass1.getSimpleName());
//getCanonicalName()方式
      try {
          Class personClass2 = Class.forName("reflect.Person");
          System.out.println("class3: " + personClass2.getCanonicalName());
      } catch (ClassNotFoundException e) {
          e.printStackTrace();
      }

打印結(jié)果如下:

class1: reflect.Person
class2: Person
class3: reflect.Person

可以看到第一種和第三種方式獲取的結(jié)果是一樣的,而只有第二種不一樣布持。及一三中獲取的是類(lèi)的完整路徑豌拙,而第二種獲取的是類(lèi)名,不包含包名题暖。而一三種有何區(qū)別可以通過(guò)類(lèi)的內(nèi)部類(lèi)來(lái)研究按傅。

2捉超、修飾符獲取
Java 中的修飾符主要有 private 、public 唯绍、static拼岳、protected、等况芒。Java 反射提供了 API 去獲取這些修飾符惜纸。

通過(guò) Class.getModifiers() 來(lái)獲取修飾符

Person person = new Person();
Class personClass = person.getClass();
System.out.println("modifiers: " + personClass.getModifiers());

結(jié)果如下:

modifiers: 1

返回的卻是一個(gè) int 型的數(shù)值。為什么會(huì)返回一個(gè)整型數(shù)值呢绝骚?這是因?yàn)橐粋€(gè)類(lèi)定義的時(shí)候可能會(huì)被多個(gè)修飾符修飾耐版,為了一并獲取,所以 Java 工程師考慮到了位運(yùn)算压汪,用一個(gè) int 數(shù)值來(lái)記錄所有的修飾符椭更,然后不同的位對(duì)應(yīng)不同的修飾符,這些修飾符對(duì)應(yīng)的位都定義在 Modifier 這個(gè)類(lèi)當(dāng)中蛾魄。

public class Modifier {
    public static final int PUBLIC           = 0x00000001;
    public static final int PRIVATE          = 0x00000002;
    public static final int PROTECTED        = 0x00000004;
    public static final int STATIC           = 0x00000008;
    public static final int FINAL            = 0x00000010;
    ......
    public static String toString(int mod) {
        StringBuilder sb = new StringBuilder();
        int len;
        if ((mod & PUBLIC) != 0)        sb.append("public ");
        if ((mod & PROTECTED) != 0)     sb.append("protected ");
        if ((mod & PRIVATE) != 0)       sb.append("private ");
        /* Canonical order */
        if ((mod & ABSTRACT) != 0)      sb.append("abstract ");
        if ((mod & STATIC) != 0)        sb.append("static ");
        if ((mod & FINAL) != 0)         sb.append("final ");
        if ((mod & TRANSIENT) != 0)     sb.append("transient ");
        if ((mod & VOLATILE) != 0)      sb.append("volatile ");
        if ((mod & SYNCHRONIZED) != 0)  sb.append("synchronized ");
        if ((mod & NATIVE) != 0)        sb.append("native ");
        if ((mod & STRICT) != 0)        sb.append("strictfp ");
        if ((mod & INTERFACE) != 0)     sb.append("interface ");
        if ((len = sb.length()) > 0)    /* trim trailing space */
            return sb.toString().substring(0, len-1);
        return "";
    }

當(dāng)然如果需要打印字符串的話,可以通過(guò) Modifier 類(lèi)提供的靜態(tài)方法toString 來(lái)獲取湿滓。

System.out.println("modifiers: " + Modifier.toString(personClass.getModifiers()));

3滴须、獲取 CLASS 的成員
一個(gè)類(lèi)的成員包括屬性、方法叽奥、構(gòu)造函數(shù)扔水。對(duì)應(yīng)到 Class 中就是 Field、Method朝氓、Constructor魔市。接下來(lái)我們通過(guò)具體實(shí)例來(lái)熟悉如何獲取這些成員。

3.1赵哲、獲取 Field
獲取指定名稱(chēng)的屬性 API:

public Field getDeclaredField(String name)
                       throws NoSuchFieldException,
                              SecurityException;
public Field getField(String name)
               throws NoSuchFieldException,
                      SecurityException

兩者的區(qū)別就是 getDeclaredField() 獲取的是 Class 中被 private 修飾的屬性待德。 getField() 方法獲取的是非私有屬性,并且 getField() 在當(dāng)前 Class 獲取不到時(shí)會(huì)向祖先類(lèi)獲取枫夺。

獲取所有的屬性将宪。

//獲取所有的屬性,但不包括從父類(lèi)繼承下來(lái)的屬性
public Field[] getDeclaredFields() throws SecurityException {}

//獲取自身的所有的 public 屬性橡庞,包括從父類(lèi)繼承下來(lái)的较坛。
public Field[] getFields() throws SecurityException {}

3.2、獲取 Method
Method 即是 Class 中的方法扒最。

public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
public Method getMethod(String name, Class<?>... parameterTypes)
public Method[] getDeclaredMethods() throws SecurityException
public Method getMethod(String name, Class<?>... parameterTypes)

3.3丑勤、獲取 Constructor

public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
public Constructor<T> getConstructor(Class<?>... parameterTypes)
public Constructor<?>[] getDeclaredConstructors() throws SecurityException 
public Constructor<?>[] getConstructors() throws SecurityException

反射運(yùn)用

以上便是簡(jiǎn)單的獲取 Class 中的字段、方法吧趣、構(gòu)造函數(shù)法竞,反射的機(jī)制便是操控這些字段耙厚、方法、構(gòu)造函數(shù)爪喘。

關(guān)于作者

專(zhuān)注于 Android 開(kāi)發(fā)多年颜曾,喜歡寫(xiě) blog 記錄總結(jié)學(xué)習(xí)經(jīng)驗(yàn),blog 同步更新于本人的公眾號(hào)秉剑,歡迎大家關(guān)注泛豪,一起交流學(xué)習(xí)~

在這里插入圖片描述
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市侦鹏,隨后出現(xiàn)的幾起案子诡曙,更是在濱河造成了極大的恐慌,老刑警劉巖略水,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件价卤,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡渊涝,警方通過(guò)查閱死者的電腦和手機(jī)慎璧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)跨释,“玉大人胸私,你說(shuō)我怎么就攤上這事”钐福” “怎么了岁疼?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)缆娃。 經(jīng)常有香客問(wèn)我捷绒,道長(zhǎng),這世上最難降的妖魔是什么贯要? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任暖侨,我火速辦了婚禮,結(jié)果婚禮上郭毕,老公的妹妹穿的比我還像新娘它碎。我一直安慰自己,他們只是感情好显押,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布扳肛。 她就那樣靜靜地躺著,像睡著了一般乘碑。 火紅的嫁衣襯著肌膚如雪挖息。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,457評(píng)論 1 311
  • 那天兽肤,我揣著相機(jī)與錄音套腹,去河邊找鬼绪抛。 笑死,一個(gè)胖子當(dāng)著我的面吹牛电禀,可吹牛的內(nèi)容都是我干的幢码。 我是一名探鬼主播,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼尖飞,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼症副!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起政基,我...
    開(kāi)封第一講書(shū)人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤贞铣,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后沮明,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體辕坝,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年荐健,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了酱畅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡江场,死狀恐怖圣贸,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情扛稽,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布滑负,位于F島的核電站在张,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏矮慕。R本人自食惡果不足惜帮匾,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望痴鳄。 院中可真熱鬧瘟斜,春花似錦、人聲如沸痪寻。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)橡类。三九已至蛇尚,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間顾画,已是汗流浹背取劫。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工匆笤, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人谱邪。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓炮捧,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親惦银。 傳聞我的和親對(duì)象是個(gè)殘疾皇子咆课,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360

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

  • 一:java概述:1,JDK:Java Development Kit璧函,java的開(kāi)發(fā)和運(yùn)行環(huán)境傀蚌,java的開(kāi)發(fā)工...
    ZaneInTheSun閱讀 2,661評(píng)論 0 11
  • 反射庫(kù)提供了一個(gè)非常豐富且精心設(shè)計(jì)的工具集,以便能夠動(dòng)態(tài)編寫(xiě)能夠操縱Java代碼的程序蘸吓。這項(xiàng)功能被大量應(yīng)用于Jav...
    Steven1997閱讀 630評(píng)論 0 2
  • 這是16年5月份編輯的一份比較雜亂適合自己觀看的學(xué)習(xí)記錄文檔善炫,今天18年5月份再次想寫(xiě)文章,發(fā)現(xiàn)簡(jiǎn)書(shū)還為我保存起的...
    Jenaral閱讀 2,770評(píng)論 2 9
  • 無(wú)私之心库继,可以調(diào)動(dòng)所有人箩艺。判斷之前以團(tuán)隊(duì)利益為出發(fā)點(diǎn),那就可以凝聚人心讓人信服宪萄,明確擺正自己位置艺谆。 自我犧牲贏的信...
    李媛even閱讀 205評(píng)論 0 0
  • 我們一生中會(huì)遇到許許多多的人,有的人可能只會(huì)出現(xiàn)我們生命中很短一陣子拜英,而有的人則可能會(huì)陪伴我們很久静汤。對(duì)于我們生命中...
    憶術(shù)品閱讀 253評(píng)論 0 0