java反射機制

3.2 反射

3.2.1 反射介紹

JAVA反射機制是在運行狀態(tài)中胸私,對于任意一個類厌处,都能夠知道這個類的所有屬性和方法;對于任意一個對象岁疼,都能夠調(diào)用它的任意一個方法和屬性阔涉;這種動態(tài)獲取的信息以及動態(tài)調(diào)用對象的方法的功能稱為java語言的反射機制

簡單的說:一個類有多個組成部分,例如:成員變量,方法瑰排,構(gòu)造方法等贯要。反射就是加載類,并解剖出類的各個組成部分

Java反射機制主要提供了以下功能:

  • 在運行時判斷任意一個對象所屬的類椭住;
  • 在運行時構(gòu)造任意一個類的對象崇渗;
  • 在運行時判斷任意一個類所具有的成員變量和方法;
  • 在運行時調(diào)用任意一個對象的方法京郑;生成動態(tài)代理

備注:程序運行時宅广,允許改變程序結(jié)構(gòu)或變量類型,這種語言稱為動態(tài)語言”傻挂。從這個觀點看乘碑,Perl,Python金拒,Ruby是動態(tài)語言兽肤,C++,Java绪抛,C#不是動態(tài)語言

3.2.2 反射的API介紹

Java反射所需要的類并不多资铡,主要有java.lang.Class類和java.lang.reflect包中的Field、Constructor幢码、Method笤休、Array類。
注意:Class類是Java反射的起源症副,針對任何一個你想探勘的類店雅,只有先為它產(chǎn)生一個Class類的對象又沾,接下來才能通過Class對象獲取其他想要的信息穗酥。

  1. Class類
  • JVM為每種類型管理著一個獨一無二的Class對象---每個類(型)都有一個Class對象
  • Java程序運行過程中嘶朱,當需要創(chuàng)建某個類的實例時珍促,JVM首先檢查所要加載的類對應的Class對象是否已經(jīng)存在。如果還不存在拆座,JVM就會根據(jù)類名查找對應的字節(jié)碼文件并加載芭梯,接著創(chuàng)建對應的Class對象暖璧,最后才創(chuàng)建出這個類的實例酱畅。
  • Java的基本數(shù)據(jù)類型都對應著一個Class對象琳袄;關鍵字void也都對應著一個Class對象;每個數(shù)組屬性也被映射為 Class 對象纺酸,所有具有相同類型和維數(shù)的數(shù)組都共享該 Class 對象
    因此窖逗,運行中的類或接口在JVM中都會有一個對應的Class對象存在,它保存了對應類或接口的類型信息餐蔬。要想獲取類或接口的相應信息滑负,需要先獲取這個Class對象在张。
  1. 加載類
  • Java中有一個Class類用于代表某一個類的字節(jié)碼
  • Class類即然代表某個類的字節(jié)碼,它當然就要提供加載某個類字節(jié)碼的方法:forName()矮慕。forName方法用于加載某個類的字節(jié)碼到內(nèi)存中,并使用class對象進行封裝
  • 另外兩種得到class對象的方式
    類名.class: Manager.class; int.class; double[].class;
    對象.getClass()
  1. 解剖類
  • Class對象提供了如下常用方法

        Public  Constructor  getConstructor(Class<?>... parameterTypes)
        Public  Method  getMethod(String name, Class<?>... parameterTypes) 
        Public  Field  getField(String name)   public
        public Constructor getDeclaredConstructor(Class... parameterTypes)
        public Method getDeclaredMethod(String name,Class... parameterTypes)
        public Field getDeclaredField(String name)  
    

這些方法分別用于從類中解剖出構(gòu)造函數(shù)啄骇、方法和成員變量(屬性)痴鳄。解剖出的成員分別使用Constructor、 Method 缸夹、 Field 對象表示痪寻。

3.2.3 反射案例

案例5:Java反射案例

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;
      }
}

interface ActionInterface {
      public void walk(int m);
}   

class SuperMan extends Person implements ActionInterface {
      private boolean blueBriefs;

      public void fly() {
                System.out.println("超人會飛耶~~");
      }

      public boolean isBlueBriefs() {
                return blueBriefs;
      }

      public void setBlueBriefs(boolean blueBriefs) {
                this.blueBriefs = blueBriefs;
      }

      @Override
      public void walk(int m) {
                System.out.println("超人會走耶~~走了" + m + "米就走不動了!");
      }
}

示例1:通過Java反射機制得到類的包名和類名

public static void main(String[] args){
    Person person = new Person();
    System.out.println("包名:" + person.getClass().getPackage().getName());
    System.out.println("完整類名:" + person.getClass().getName());
}

示例2:驗證所有的類都是Class類的實例對象

public static void main(String[] args){
    // 定義兩個類型都未知的Class虽惭,設置初值為null橡类,看看如何給它們賦值成Person類
    Class<?> class1 = null;
    Class<?> class2 = null;
    // 寫法1,可能拋出 ClassNotFoundException 異常芽唇,多用這個寫法
    try {
            class1 = Class.forName("shuang.com.demo.Person");//包名要寫正確顾画,不然拋異常
            System.out.println("寫法1,包名:" + class1.getPackage().getName() + " , 完整類名:" + class1.getName());
    } catch (ClassNotFoundException e) {
            System.out.println("寫法1找不到類");
    }
    // 寫法2
    class2 = Person.class;
    System.out.println("寫法2匆笤,包名:" + class2.getPackage().getName() + " , 完整類名:" + class2.getName());
 }

示例3:通過Java反射機制研侣,用 Class 創(chuàng)建類對象,這也就是反射存在的意義所在

public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException{
    Class<?> class1 = null;
    class1 = Class.forName("shuang.com.demo.Person");
    // 由于這里不能帶參數(shù)炮捧,所以你要實例化的這個類Person庶诡,一定要有無參構(gòu)造函數(shù)
    Person person = (Person) class1.newInstance();
    person.setName("xiaoming");
    person.setAge(20);
    System.out.println(person.getName() + " , " + person.getAge());
}

示例4:通過Java反射機制得到一個類的構(gòu)造函數(shù),并實現(xiàn)創(chuàng)建帶參實例對象

public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException,IllegalArgumentException, InvocationTargetException{
    Class<?> class1 = null;
    Person person1 = null;
    Person person2 = null;
    class1 = Class.forName("shuang.com.demo.Person");
    Constructor<?>[] constructors = class1.getConstructors();
    person1 = (Person) constructors[0].newInstance();
    person1.setName("xiaoming");
    person1.setAge(20);
    System.out.println(person1.getName() + " , " + person1.getAge());
    person2 = (Person) constructors[1].newInstance(21, "xiaohong");
    System.out.println(person2.getName() + " , " + person2.getAge());
}

示例5:通過Java反射機制操作成員變量, set 和 get

public static void main(String args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException, SecurityException{
    Class<?> class1 = Class.forName("shuang.com.demo.Person");
    Object obj = class1.newInstance();
    Field personNameField = class1.getDeclaredField("name");
    personNameField.setAccessible(true); // 取消訪問檢查
    personNameField.set(obj, "小虎");
    System.out.println("修改屬性之后得到屬性變量的值:" + personNameField.get(obj));
}

示例6:通過Java反射機制得到類的一些屬性:繼承的接口咆课、父類末誓、函數(shù)信息、成員信息书蚪、類型等

public static void main(String[] args) throws ClassNotFoundException{
    Class<?> class1 = Class.forName("shuang.com.demo.SuperMan");

    // 取得父類名稱
    Class<?> superclass = class1.getSuperclass();
    System.out.println("SuperMan類的父類名:" + superclass.getName());

    Field[] fields = class1.getDeclaredFields();
    for (int i = 0; i < fields.length; i++) {
              System.out.println("類中的成員" + i + ": " + fields[i]);
    }

    // 取得類方法
    Method[] methods = class1.getDeclaredMethods();
    for (int i = 0; i < methods.length; i++) {
              System.out.println("取得SuperMan類的方法" + i + ":");
              System.out.println("函數(shù)名:" + methods[i].getName());
              System.out.println("函數(shù)返回類型:" + methods[i].getReturnType());
              System.out.println("函數(shù)訪問修飾符:" + Modifier.toString(methods[i].getModifiers()));
              System.out.println("函數(shù)代碼寫法: " + methods[i]);
    }

    // 取得類實現(xiàn)的接口喇澡,因為接口類也屬于Class,所以得到接口中的方法也是一樣的方法得到哈
    Class<?> interfaces[] = class1.getInterfaces();
    for (int i = 0; i < interfaces.length; i++) {
              System.out.println("實現(xiàn)的接口類名: " + interfaces[i].getName());
    }
}

示例7:通過Java反射機制調(diào)用類方法

public static void main(String[] args)throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException,InstantiationException, InvocationTargetException{
    Class<?> class1 = Class.forName("shuang.com.demo.SuperMan");

    System.out.println("調(diào)用無參方法fly():");
    Method method = class1.getMethod("fly");
    method.invoke(class1.newInstance());

    System.out.println("調(diào)用有參方法walk(int m):");
    method = class1.getMethod("walk", int.class);
    method.invoke(class1.newInstance(), 100);
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末善炫,一起剝皮案震驚了整個濱河市撩幽,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌箩艺,老刑警劉巖窜醉,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異艺谆,居然都是意外死亡榨惰,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門静汤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來琅催,“玉大人居凶,你說我怎么就攤上這事√俾眨” “怎么了侠碧?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長缠黍。 經(jīng)常有香客問我弄兜,道長,這世上最難降的妖魔是什么瓷式? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任替饿,我火速辦了婚禮,結(jié)果婚禮上贸典,老公的妹妹穿的比我還像新娘视卢。我一直安慰自己,他們只是感情好廊驼,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布据过。 她就那樣靜靜地躺著,像睡著了一般蔬充。 火紅的嫁衣襯著肌膚如雪蝶俱。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天饥漫,我揣著相機與錄音榨呆,去河邊找鬼。 笑死庸队,一個胖子當著我的面吹牛积蜻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播彻消,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼竿拆,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了宾尚?” 一聲冷哼從身側(cè)響起丙笋,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎煌贴,沒想到半個月后御板,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡牛郑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年怠肋,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片淹朋。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡笙各,死狀恐怖钉答,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情杈抢,我是刑警寧澤数尿,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站惶楼,受9級特大地震影響砌创,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鲫懒,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望刽辙。 院中可真熱鬧窥岩,春花似錦、人聲如沸宰缤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽慨灭。三九已至朦乏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間氧骤,已是汗流浹背呻疹。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留筹陵,地道東北人刽锤。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像朦佩,于是被迫代替她去往敵國和親并思。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

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

  • 一语稠、概述 Java反射機制定義 Java反射機制是在運行狀態(tài)中宋彼,對于任意一個類,都能夠知道這個類中的所有屬性和方法...
    CoderZS閱讀 1,639評論 0 26
  • 寫在前面的話:很多人會說我直接new一個對象不就完了么仙畦,干嘛還用反射來獲取對象输涕。因為new屬于靜態(tài)編譯,而反射屬于...
    iDaniel閱讀 8,617評論 1 4
  • 一议泵、概述 1占贫、Java反射機制(Java-Reflect): 在運行狀態(tài)中,對于任意一個類先口,都能夠知道這個類中的所...
    年少懵懂丶流年夢閱讀 4,419評論 0 5
  • 好幾天沒寫日記了型奥,并不是因為忘了瞳收,而是太忙也太累了,晚上回來沒精力再做其他事情厢汹,洗洗就睡了螟深,上床連衣服都懶...
    Edway閱讀 157評論 0 0
  • 每個人的內(nèi)心都是不一樣的界弧,恰如世上沒有兩朵相同的花兒。但躁動的心會忘掉自己的特點搭综,只知道攀比垢箕,這是人性的愚昧。守住...
    關中人閱讀 248評論 0 1