反射-Day13(2019/5/10)-JAVA

反射

image.png

JAVA 反射機制是在運行狀態(tài)中胚吁,對于任意一個類牙躺,都能夠知道這個類的所有屬性和方 法;對于任意一個對象腕扶,都能夠調(diào)用它的任意一個方法和屬性孽拷;這種動態(tài)獲取的信息以及動態(tài)調(diào)用對象的方法的功能稱為 java 語言的反射機制。

Java 反射機制半抱,可以實現(xiàn)以下功能:
①在運行時判斷任意一個對象所屬的類脓恕;
②在運行時構(gòu)造任意一個類的對象膜宋;
③在運行時判斷任意一個類所具有的成員變量和方法;
④在運行時調(diào)用任意一個對象的方法炼幔; ⑤生成動態(tài)代理秋茫。

一、 獲取源頭 Class(重點)

①Class.forName(”包名.類名”)//一般盡量采用該形式
②類.class
③對象.getClass()

public class  Source {
public static void main(String[] args) {
//第一種方式:對象.class
Source s=new Source();
Class<?>c1=s.getClass();
//第二種方式:類.class
Class<?>c2=Source.class;
//第三種方式(推薦方式): Class.forName()
Class<?>c3=null;
try {
c3=Class.forName("com.shsxt.ref.simple.Source");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println(c1.getName());
System.out.println(c2.getName());
System.out.println(c3.getName());
}
}


\color{red}{注意}

1.創(chuàng)建對象的時候,拿到的都是當(dāng)天前類型Class對象的一個鏡像|賦值體

2.在類加載的時候,會在內(nèi)存中存在當(dāng)天前類型的一個Class對象,一個類的Class對象中存儲這個類的所有信息(屬性,方法,構(gòu)造器...)

3.只要我們能夠獲取這個類型的Class對象,就可以對這個類做一切操作

Class 類的實例表示正在運行的 Java 應(yīng)用程序中的類和接口

public class ReflectDemo02 {
    public static void main(String[] args) throws ClassNotFoundException{
        //1.對象.getClass()
        Class cls1="哈哈".getClass();
        Class cls2="呵呵".getClass();
        System.out.println(cls1==cls2);
        
        //2.類名.class
        Class cls3=String.class;
        System.out.println(cls1==cls3);
        System.out.println(cls3);
        
        //3.Class.forName("類的權(quán)限命名:包名+類名")   推薦
        Class cls4=Class.forName("java.lang.String");
        System.out.println(cls3==cls4);
        
        //4.根據(jù)子類的Class對象獲取父類的Class對象
        Class cls5=cls4.getSuperclass();
        System.out.println(cls5);
        
        //5.獲取基本數(shù)據(jù)類型的Class對象
        Class base1=int.class;
        System.out.println(base1);
        Class cls6=Integer.class;
        System.out.println(base1==cls6);
        Class base2=Integer.TYPE;  //得到對應(yīng)的基本數(shù)據(jù)類型的class對象
        System.out.println(base1==base2);
        
        //常用的方法
        //1.getName() 包名+類名
        System.out.println(cls5.getName());
        
        //2. Class<?>[] getInterfaces()  
        Class[] arr=cls4.getInterfaces();
        System.out.println(Arrays.toString(arr));
        
        //3.String getSimpleName()  
        System.out.println(cls4.getSimpleName());
        
        //4.boolean  isInterface()  isPrimitive() 
        System.out.println(Integer.class.isPrimitive());
        System.out.println(Integer.TYPE.isPrimitive());
        
    }
}



二乃秀、實例化對象****(****重點****)**

1)通過反射獲取到類中的構(gòu)造器

2)根據(jù)構(gòu)造器創(chuàng)建對象

l 構(gòu)造器Constructor對象.newInstance(實參)方法

l 直接通過class類的newIntance()方法創(chuàng)建對象,方法沒有參數(shù) 調(diào)用空構(gòu)造

構(gòu)造器方法

image.png

注意****:newInstance()****是調(diào)用空構(gòu)造肛著,如果空構(gòu)造不存在,會出現(xiàn)異常跺讯。由此可知枢贿,使用其他構(gòu)造器創(chuàng)建對象比較麻煩,使用空構(gòu)造非常簡單刀脏。 確本旨裕空構(gòu)造存在.

public class ReflectDemo03 {
    public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
        //1.先獲取類的Class
        Class cls=Person.class;
        //2.通過Class類中的方法,獲取到Person類中的構(gòu)造器
        
        /*
         *   Constructor<T> getConstructor(Class<?>... parameterTypes) 
                      返回一個 Constructor 對象,它反映此 Class 對象所表示的類的指定公共構(gòu)造方法愈污。 
             Constructor<?>[] getConstructors() 
                      返回一個包含某些 Constructor 對象的數(shù)組耀态,這些對象反映此 Class 對象所表示的類的所有公共構(gòu)造方法。 
         */
        Constructor con1=cls.getConstructor(int.class,String.class,int.class);
        Person p=(Person) con1.newInstance(01,"盧妹妹",18);
        System.out.println(p);
        
        Person p1=(Person)cls.newInstance();
        System.out.println(p1);
        
        /*
         *   Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 
                      返回一個 Constructor 對象暂雹,該對象反映此 Class 對象所表示的類或接口的指定構(gòu)造方法茫陆。 
             Constructor<?>[] getDeclaredConstructors() 
                      返回 Constructor 對象的一個數(shù)組,這些對象反映此 Class 對象表示的類聲明的所有構(gòu)造方法擎析。 
         */
        Constructor<Person>[] cons=cls.getDeclaredConstructors();
        System.out.println(Arrays.toString(cons));
        //私有的構(gòu)造器
        //放開權(quán)限
        cons[1].setAccessible(true);  //權(quán)限方法
        Person p3=cons[1].newInstance(02,"盧雙雙");
        cons[1].setAccessible(false); 
        System.out.println(p3);
        
        
    }
}


|

三:屬性和方法

獲取所有屬性(包括父類或接口) 簿盅,使用 Field 即可操作

image.png

獲取所有方法(包括父類或接口),使用 Method 即可揍魂。

image.png
package com.shsxt.ref01;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;

public class ReflectDemo04 {
    public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException {
//      testField(Person.class);
        testMethod(Person.class);
    }
    
    /*
     * 操作方法   調(diào)用方法,能給方法傳遞實參
     * 
     *  Method getDeclaredMethod(String name, Class<?>... parameterTypes) 
            返回一個 Method 對象桨醋,該對象反映此 Class 對象所表示的類或接口的指定已聲明方法。 
        Method[] getDeclaredMethods() 
        Method getMethod(String name, Class<?>... parameterTypes) 
            返回一個 Method 對象现斋,它反映此 Class 對象所表示的類或接口的指定公共成員方法喜最。 
        Method[] getMethods() 
            返回一個包含某些 Method 對象的數(shù)組,這些對象反映此 Class 對象所表示的類或接口(包括那些由該類或接口聲明的以及從超類和超接口繼承的那些的類或接口)的公共 member 方法庄蹋。 
     */
    public static void testMethod(Class cls) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException{
        Method[] arr=cls.getMethods();
        Person p=(Person) cls.newInstance();
//      Method me=cls.getDeclaredMethod("setAge", int.class);
        Method me=cls.getDeclaredMethod("toString");
        System.out.println(me.invoke(p));;
        System.out.println(p.getAge());
//      System.out.println(Arrays.toString(arr));
        //靜態(tài)方法執(zhí)行的時候,invoke第一個參數(shù)可以為null
        cls.getMethod("haha").invoke(null);
    }
    
    /*
     * 反射操作類中的字段  能設(shè)置值  能獲取值
     * Field getDeclaredField(String name) 
                  返回一個 Field 對象瞬内,該對象反映此 Class 對象所表示的類或接口的指定已聲明字段。 
       Field[] getDeclaredFields() 
                  返回 Field 對象的一個數(shù)組限书,這些對象反映此 Class 對象所表示的類或接口所聲明的所有字段虫蝶。 
       Field getField(String name) 
                  返回一個 Field 對象,它反映此 Class 對象所表示的類或接口的指定公共成員字段倦西。 
       Field[] getFields()  
     */
    public static void testField(Class cls) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException{
        Field name=cls.getDeclaredField("name");
        //Object get(Object obj) 返回指定對象上此 Field 表示的字段的值能真。 
        name.setAccessible(true);
        //void set(Object obj, Object value)  
        Person p=new Person(05,"大力",18);
        name.set(p, "大力水手");
        System.out.println(name.get(p));
        System.out.println(name.getName());
        System.out.println(Modifier.toString(name.getModifiers()));
    }
}


四:修飾符

獲取修飾符,使用 Modifier 即可

image.png

五:類加載器

在 java 中有三種類類加載器: ⑴Bootstrap ClassLoader 此加載器采用 c++編寫,一般開發(fā)中很少見粉铐。 ⑵Extension ClassLoader 用來進行擴展類的加載疼约,一般對應(yīng)的是 jre\lib\ext 目錄中的類 ⑶AppClassLoader 加載 classpath 指定的類,是最常用的加載器蝙泼。同時也是 java 中默認的加載器程剥。 了解即可。

image.png

了解一下類的生命周期 : 在一個類編譯完成之后汤踏,下一步就需要開始使用類织鲸,如果要使用一個類,肯定離不開 JVM茎活。 在程序執(zhí)行中 JVM 通過裝載鏈接琢唾,初始化這 3 個步驟完成载荔。 類的裝載是通過類加載器完成的,加載器將.class 文件的二進制文件裝入 JVM 的方法區(qū)采桃,并且在堆區(qū)創(chuàng)建描述這個類的 java.lang.Class 對象懒熙。用來封裝數(shù)據(jù)。 但是同一個類只會被類裝載器裝載一次普办。 鏈接就是把二進制數(shù)據(jù)組裝為可以運行的狀態(tài)工扎。鏈接分為校驗,準備衔蹲,解析這 3 個階段 1肢娘、校驗一般用來確認此二進制文件是否適合當(dāng)前的 JVM(版本), 2舆驶、準備就是為靜態(tài)成員分配內(nèi)存空間橱健。并設(shè)置默認值 3、解析指的是轉(zhuǎn)換常量池中的代碼作為直接引用的過程沙廉,直到所有的符號引用都可以 被運行程序使用(建立完整的對應(yīng)關(guān)系) 完成之后拘荡,類型也就完成了初始化,初始化之后類的對象就可以正常使用了撬陵,直到一個 對象不再使用之后珊皿,將被垃圾回收。釋放空間巨税。當(dāng)沒有任何引用指向 Class 對象時就會被卸載蟋定,結(jié)束類的生命周期。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末草添,一起剝皮案震驚了整個濱河市溢吻,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖促王,帶你破解...
    沈念sama閱讀 216,919評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件犀盟,死亡現(xiàn)場離奇詭異,居然都是意外死亡蝇狼,警方通過查閱死者的電腦和手機阅畴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來迅耘,“玉大人贱枣,你說我怎么就攤上這事〔ǎ” “怎么了纽哥?”我有些...
    開封第一講書人閱讀 163,316評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長栖秕。 經(jīng)常有香客問我春塌,道長,這世上最難降的妖魔是什么簇捍? 我笑而不...
    開封第一講書人閱讀 58,294評論 1 292
  • 正文 為了忘掉前任只壳,我火速辦了婚禮,結(jié)果婚禮上暑塑,老公的妹妹穿的比我還像新娘吼句。我一直安慰自己,他們只是感情好事格,可當(dāng)我...
    茶點故事閱讀 67,318評論 6 390
  • 文/花漫 我一把揭開白布惕艳。 她就那樣靜靜地躺著,像睡著了一般驹愚。 火紅的嫁衣襯著肌膚如雪尔艇。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,245評論 1 299
  • 那天么鹤,我揣著相機與錄音终娃,去河邊找鬼。 笑死蒸甜,一個胖子當(dāng)著我的面吹牛棠耕,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播柠新,決...
    沈念sama閱讀 40,120評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼窍荧,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了恨憎?” 一聲冷哼從身側(cè)響起蕊退,我...
    開封第一講書人閱讀 38,964評論 0 275
  • 序言:老撾萬榮一對情侶失蹤郊楣,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后瓤荔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體净蚤,經(jīng)...
    沈念sama閱讀 45,376評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,592評論 2 333
  • 正文 我和宋清朗相戀三年输硝,在試婚紗的時候發(fā)現(xiàn)自己被綠了今瀑。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,764評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡点把,死狀恐怖橘荠,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情郎逃,我是刑警寧澤哥童,帶...
    沈念sama閱讀 35,460評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站褒翰,受9級特大地震影響贮懈,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜影暴,卻給世界環(huán)境...
    茶點故事閱讀 41,070評論 3 327
  • 文/蒙蒙 一错邦、第九天 我趴在偏房一處隱蔽的房頂上張望探赫。 院中可真熱鬧型宙,春花似錦、人聲如沸伦吠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽毛仪。三九已至搁嗓,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間箱靴,已是汗流浹背腺逛。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留衡怀,地道東北人棍矛。 一個月前我還...
    沈念sama閱讀 47,819評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像抛杨,于是被迫代替她去往敵國和親够委。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,665評論 2 354

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