java反射

一、前置知識(shí)點(diǎn)

1、運(yùn)行java程序需要java虛擬機(jī)(JVM)
2淀歇、我們編寫(xiě)的java代碼需要被編譯成.class文件
3、.class文件會(huì)被類(lèi)加載器加載到j(luò)ava虛擬機(jī)當(dāng)中
4匈织、.class文件記錄著類(lèi)的所有的信息

個(gè)人理解:

計(jì)算機(jī)通過(guò)加載到的.class文件已經(jīng)知道類(lèi)的所有信息了浪默,但是為了讓人也能知道這個(gè)類(lèi)中描述的所有信息牡直,所以才有了反射,就是將類(lèi)的詳細(xì)信息以對(duì)象的形式表達(dá)出來(lái)纳决,方便人去進(jìn)行手動(dòng)管理碰逸。

就像汽車(chē)一樣,原本我們使用汽車(chē)能開(kāi)就可以了阔加,但是難免有人想改裝它饵史,這時(shí)候就需要提供這個(gè)車(chē)子的架構(gòu)圖了。個(gè)人覺(jué)得之所以有反射胜榔,就是這個(gè)道理胳喷。

二、測(cè)試實(shí)例

(1)基礎(chǔ)類(lèi)

測(cè)試注解

package com.suncy.article.article10;

import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyRefAnnotation {
}

測(cè)試基礎(chǔ)類(lèi)
兩個(gè)構(gòu)造方法夭织,兩個(gè)成員變量吭露,兩個(gè)成員方法

package com.suncy.article.article10;

import org.springframework.beans.factory.annotation.Value;

//添加測(cè)試注解
@MyRefAnnotation
public class MyRefTest {
    public int a;
    private String b;
    public MyRefTest() {
    }

    private MyRefTest(String b) {
        this.b = b;
    }

    public MyRefTest(int a) {
        this.a = a;
    }

    @Value("444")
    public void testA(String a) throws Exception{
        System.out.println("ttttt" + a);
    }

    private void testB() {
    }
}

(2) Class<?> 對(duì)象提供的一些方法

package com.suncy.article.article10;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;

public class ReflexTestMain {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException,
            IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
        //基本獲取方法
        System.out.println("=====================獲取Class<?>的三種方式=====================");
        MyRefTest myRefTest = new MyRefTest();
        Class<?> cls = myRefTest.getClass();
        System.out.println("myRefTest.getClass() : " + cls);

        Class<?> cls1 = MyRefTest.class;
        System.out.println("MyRefTest.class : " + cls1);

        Class<?> cls2 = Class.forName("com.suncy.article.article10.MyRefTest");
        System.out.println("Class.forName(xxx) : " + cls2);
        System.out.println();

        //基本使用方法
        //一、獲取構(gòu)造方法
        //1尊惰、獲取所有的公有構(gòu)造方法
        System.out.println("=======================獲取Constructor<?>=========================");
        Constructor<?>[] constructors = cls.getConstructors();
        System.out.println("cls.getConstructors() : " + Arrays.toString(constructors));

        //2讲竿、獲取所有構(gòu)造方法 包括私有的 受保護(hù)的
        Constructor<?>[] constructors1 = cls.getDeclaredConstructors();
        System.out.println("cls.getDeclaredConstructors() : " + Arrays.toString(constructors1));

        //3、獲取公有的無(wú)參構(gòu)造方法
        Constructor<?> constructor = cls.getConstructor();
        System.out.println("cls.getConstructor() : " + constructor);

        //4弄屡、調(diào)用構(gòu)造方法 生成對(duì)象
        System.out.println("通過(guò)constructor實(shí)例化對(duì)象");
        MyRefTest myRefTest1 = (MyRefTest) constructor.newInstance();
        System.out.println("myRefTest : " + myRefTest);
        System.out.println("myRefTest1 : " + myRefTest1);
        System.out.println();

        System.out.println("=======================獲取Field=========================");
        //二题禀、獲取成員變量
        //1、獲取所有的公有字段
        Field[] fields = cls.getFields();
        System.out.println("cls.getFields() : " + Arrays.toString(fields));

        //2膀捷、獲取所有的字段
        Field[] fields1 = cls.getDeclaredFields();
        System.out.println("cls.getDeclaredFields() : " + Arrays.toString(fields1));

        //3投剥、獲取某個(gè)公有字段
        Field fieldA = cls.getField("a");
        System.out.println("cls.getField(xx) : " + fieldA);

        //4、獲取某個(gè)字段担孔,包含私有的
        Field fieldB = cls.getDeclaredField("b");
        System.out.println("cls.getDeclaredField(xx) : " + fieldB);
        System.out.println();

        System.out.println("======================獲取Method=========================");
        //三、獲取成員方法
        //1吃警、獲取所有公有的成員方法
        Method[] methods = cls.getMethods();
        System.out.println("cls.getMethods() : " + Arrays.toString(methods));

        //2糕篇、獲取所有的成員方法 包含私有
        Method[] methods1 = cls.getDeclaredMethods();
        System.out.println("cls.getDeclaredMethods() : " + Arrays.toString(methods1));

        //3、獲取某個(gè)公有字段
        Method methodA = cls.getMethod("testA", String.class);
        System.out.println("cls.getMethod(xx, String.class) : " + methodA);

        //4酌心、獲取某個(gè)字段拌消,包含私有的
        Method methodB = cls.getDeclaredMethod("testB");
        System.out.println("cls.getDeclaredMethod(xx) : " + methodB);
        System.out.println();

        System.out.println("======================獲取類(lèi)上的Annotation==========================");

        //四、獲取類(lèi)注解
        //1安券、獲取類(lèi)上所有的注解
        Annotation[] annotations = cls.getAnnotations();
        System.out.println("cls.getAnnotations() : " + Arrays.toString(annotations));

        //2墩崩、獲取類(lèi)上特定的注解
        MyRefAnnotation annotation = cls.getAnnotation(MyRefAnnotation.class);
        System.out.println("cls.getAnnotation(xx) : " + annotation);

        //3、獲取不存在的注解 會(huì)返回null
        Override annotation1 = cls.getAnnotation(Override.class);
        System.out.println("cls.getAnnotation(xx) : " + annotation1);
        System.out.println();

        //五侯勉、判斷類(lèi)的類(lèi)型
        System.out.println("======================判斷類(lèi)的類(lèi)型==========================");
        System.out.println("cls.isArray() : " + cls.isArray());                  //數(shù)組類(lèi)
        System.out.println("cls.isAnnotation() : " + cls.isAnnotation());             //注解類(lèi)
        System.out.println("cls.isAnnotationPresent(xx) : " + cls.isAnnotationPresent(MyRefAnnotation.class));        //特定注解類(lèi)
        System.out.println("cls.isInterface() : " + cls.isInterface());               //接口類(lèi)
        System.out.println("cls.isLocalClass() : " + cls.isLocalClass());              //局部類(lèi)
        System.out.println("cls.isEnum() : " + cls.isEnum());                   //枚舉類(lèi)
        System.out.println("cls.isAnonymousClass() : " + cls.isAnonymousClass());         //匿名類(lèi)
        System.out.println("cls.isMemberClass() : " + cls.isMemberClass());            //內(nèi)部類(lèi)
        System.out.println("cls.isInstance(xx) : " + cls.isInstance(myRefTest));      //判斷對(duì)象是否是該類(lèi)實(shí)例
        System.out.println();

        System.out.println("=======================Class<?>中的其他方法=========================");
        //六鹦筹、其他方法
        //獲取類(lèi)加載器
        ClassLoader classLoader = cls.getClassLoader();
        System.out.println("cls.getClassLoader() : " + classLoader);

        Class<?>[] classes = cls.getClasses();
        System.out.println("cls.getClasses() : " + Arrays.toString(classes));

        Class<?>[] classes1 = cls.getDeclaredClasses();
        System.out.println("cls.getDeclaredClasses() : " + Arrays.toString(classes1));

        //獲取類(lèi)的名稱(chēng)(完整路徑)
        String name = cls.getName();
        System.out.println("cls.getName() : " + name);

        //獲取類(lèi)的名稱(chēng)(類(lèi)名稱(chēng))
        String name1 = cls.getSimpleName();
        System.out.println("cls.getSimpleName() : " + name1);

        //獲取類(lèi)的名稱(chēng)(獲取所傳類(lèi)從java語(yǔ)言規(guī)范定義的格式輸出)
        String name2 = cls.getCanonicalName();
        System.out.println("cls.getCanonicalName() : " + name2);

        //獲取父類(lèi)類(lèi)型
        Class<?> clsSuperclass = cls.getSuperclass();
        System.out.println("cls.getSuperclass() : " + clsSuperclass);

        //獲取接口類(lèi)型
        Class<?>[] clsSuperclass1 = cls.getInterfaces();
        System.out.println("cls.getInterfaces() : " + Arrays.toString(clsSuperclass1));

        //獲取包名
        Package clsPackage = cls.getPackage();
        System.out.println("cls.getPackage() : " + clsPackage);
    }
}

響應(yīng)結(jié)果

image.png

image.png

(3) Method、Field址貌、Annotation提供的一些方法

package com.suncy.article.article10;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;

public class ReflexTestMain1 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException,
            IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
        Class<?> cls = Class.forName("com.suncy.article.article10.MyRefTest");

        //拿到Constructor對(duì)象
        Constructor<MyRefTest> constructor = (Constructor<MyRefTest>) cls.getConstructor();
        System.out.println("拿到MyRefTest類(lèi)的Constructor對(duì)象 : " + constructor);

        //根據(jù)constructor實(shí)例化對(duì)象
        MyRefTest myRefTest = constructor.newInstance();
        System.out.println("根據(jù)這個(gè)myRefTest的constructor構(gòu)造對(duì)象(constructor.newInstance()) : " + myRefTest);

        //拿到cls所有方法
        Method[] methods = cls.getMethods();
        System.out.println("拿到這個(gè)類(lèi)所有公有成員方法(cls.getMethods()) : " + Arrays.toString(methods));
        System.out.println();

        //拿到cls特定的某個(gè)方法 執(zhí)行myRefTest對(duì)象的這個(gè)特定的方法
        System.out.println("=============testA方法對(duì)應(yīng)的Method對(duì)象================");
        Method methodTestA = cls.getMethod("testA", String.class);
        System.out.println("拿到testA方法的Method : " + methodTestA);

        // 調(diào)用對(duì)象方法
        System.out.println("調(diào)用testA方法 : ");
        methodTestA.invoke(myRefTest, "22312312");

        //拿到這個(gè)特定Method方法上的注解
        System.out.println("拿到methodA方法上的注解 : " + Arrays.toString(methodTestA.getDeclaredAnnotations()));
        //拿到這個(gè)特定Method方法上的異常
        System.out.println("拿到methodA方法上的異常 : " + Arrays.toString(methodTestA.getExceptionTypes()));
        System.out.println();

        //給myRefTest對(duì)象的a字段設(shè)置值 通過(guò)Field對(duì)象拿到這個(gè)a字段的值
        System.out.println("=============a字段對(duì)應(yīng)的Field對(duì)象================");
        myRefTest.a = 34;
        Field fieldA = cls.getField("a");
        System.out.println("拿到a字段Field : " + fieldA);
        System.out.println("拿到字段a的值 : " + fieldA.getInt(myRefTest));

        System.out.println("是否能反射出a字段屬性值 : " + fieldA.isAccessible());
        //設(shè)置是否能反射該屬性數(shù)
        System.out.println("修改是否能反射a字段屬性值 : fieldA.setAccessible(true)");
        fieldA.setAccessible(true);
        System.out.println("是否能反射出a字段屬性值 : " + fieldA.isAccessible());
        System.out.println("是否是枚舉類(lèi)型的元素 : " + fieldA.isEnumConstant());
        System.out.println();

        //拿到cls類(lèi)上持有的注解
        System.out.println("==========MyRefAnnotation注解對(duì)應(yīng)的Annotation對(duì)象================");
        Annotation annotation = cls.getAnnotation(MyRefAnnotation.class);
        System.out.println("獲取MyRefAnnotation注解的Annotation : " + annotation);

        //返回cls類(lèi)的規(guī)范名稱(chēng)(獲取所傳類(lèi)從java語(yǔ)言規(guī)范定義的格式輸出)
        System.out.println("拿到類(lèi)的規(guī)范名稱(chēng) : " + cls.getCanonicalName());

        //返回注解的注解類(lèi)型
        System.out.println("拿到注解的annotationType : " + annotation.annotationType());
        //返回注解的規(guī)范名稱(chēng)(獲取所傳類(lèi)從java語(yǔ)言規(guī)范定義的格式輸出)
        System.out.println("拿到注解的規(guī)范名稱(chēng) : " + annotation.annotationType().getCanonicalName());
    }
}

響應(yīng)結(jié)果

image.png

三铐拐、總結(jié)

1徘键、反射相關(guān)類(lèi):Class、Constructor遍蟋、Method吹害、Field、Annotation虚青。
2它呀、代理常用的一種方式是: methodTestA.invoke(myRefTest, "22312312");
methodTestA表示一個(gè)特定的Method對(duì)象。myRefTest表示對(duì)象棒厘。22312312表示參數(shù)纵穿、參數(shù)數(shù)量需要去看Method指定方法的參數(shù)是多少。
3绊谭、多寫(xiě)demo測(cè)試一下政恍,更為直觀,印象更深达传。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末篙耗,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子宪赶,更是在濱河造成了極大的恐慌宗弯,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件搂妻,死亡現(xiàn)場(chǎng)離奇詭異蒙保,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)欲主,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén)邓厕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人扁瓢,你說(shuō)我怎么就攤上這事详恼。” “怎么了引几?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵昧互,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我伟桅,道長(zhǎng)敞掘,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任楣铁,我火速辦了婚禮玖雁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘民褂。我一直安慰自己茄菊,他們只是感情好疯潭,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著面殖,像睡著了一般竖哩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上脊僚,一...
    開(kāi)封第一講書(shū)人閱讀 51,301評(píng)論 1 301
  • 那天相叁,我揣著相機(jī)與錄音,去河邊找鬼辽幌。 笑死增淹,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的乌企。 我是一名探鬼主播虑润,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼加酵!你這毒婦竟也來(lái)了拳喻?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤猪腕,失蹤者是張志新(化名)和其女友劉穎冗澈,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體陋葡,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡亚亲,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了腐缤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片捌归。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖岭粤,靈堂內(nèi)的尸體忽然破棺而出陨溅,到底是詐尸還是另有隱情,我是刑警寧澤绍在,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站雹有,受9級(jí)特大地震影響偿渡,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜霸奕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一溜宽、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧质帅,春花似錦适揉、人聲如沸留攒。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)炼邀。三九已至,卻和暖如春剪侮,著一層夾襖步出監(jiān)牢的瞬間拭宁,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工瓣俯, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留杰标,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓彩匕,卻偏偏與公主長(zhǎng)得像腔剂,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子驼仪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

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

  • Java反射 概述 Java反射機(jī)制可以讓我們?cè)诰幾g期(Compile Time)之外的運(yùn)行期(Runtime)檢...
    Leocat閱讀 1,135評(píng)論 0 0
  • 一掸犬、反射 通過(guò)Class實(shí)例獲取 class 信息的方法稱(chēng)為反射(Reflection)。 (一) Class 類(lèi)...
    瀑月流光閱讀 808評(píng)論 0 0
  • java反射主要從以下幾個(gè)方面理解 理解 Class 類(lèi) 理解 Java 的類(lèi)加載機(jī)制 學(xué)會(huì)使用 ClassLoa...
    境里婆娑閱讀 11,586評(píng)論 0 11
  • Java 語(yǔ)言允許通過(guò)程序化的方式間接對(duì) Class 進(jìn)行操作谅畅, Class 文件由類(lèi)裝載器裝載后登渣,在 JVM 中...
    deniro閱讀 1,344評(píng)論 0 40
  • 動(dòng)態(tài)語(yǔ)言 動(dòng)態(tài)語(yǔ)言,是指程序在運(yùn)行時(shí)可以改變其結(jié)構(gòu):新的函數(shù)可以被引進(jìn)毡泻,已有的函數(shù)可以被刪除等在結(jié)構(gòu)上的變化胜茧。比如...
    諾天高云淡閱讀 357評(píng)論 1 0