Java基礎(chǔ)-反射-反射的使用

Java工程師知識樹 / Java基礎(chǔ)


反射的使用

通過反射查看類信息

  • 類的構(gòu)造方法:Class類提供了用于獲取某個類的構(gòu)造方法荒勇。
Constructor getConstructor(Class<?>... parameterTypes)     根據(jù)構(gòu)造函數(shù)的參數(shù)划鸽,返回一個具體的具有public屬性的構(gòu)造函數(shù)
Constructor getConstructors()     返回所有具有public屬性的構(gòu)造函數(shù)數(shù)組
Constructor getDeclaredConstructor(Class<?>... parameterTypes)     根據(jù)構(gòu)造函數(shù)的參數(shù)塞俱,返回一個具體的構(gòu)造函數(shù)(不分public和非public屬性)
Constructor getDeclaredConstructors()    返回該類中所有的構(gòu)造函數(shù)數(shù)組(不分public和非public屬性)
  • 類的屬性:Class類提供了獲取成員屬性的方法
Field getField(String name)    根據(jù)變量名限府,返回一個具體的具有public屬性的成員變量
Field[] getFields()    返回具有public屬性的成員變量的數(shù)組
Field getDeclaredField(String name)    根據(jù)變量名,返回一個成員變量(不分public和非public屬性)
Field[] getDelcaredFields()    返回所有成員變量組成的數(shù)組(不分public和非public屬性)
  • 類的方法:Class類提供了獲取成員方法的方法
Method getMethod(String name, Class<?>... parameterTypes)    根據(jù)方法名和參數(shù)灿渴,返回一個具體的具有public屬性的方法
Method[] getMethods()    返回所有具有public屬性的方法數(shù)組
Method getDeclaredMethod(String name, Class<?>... parameterTypes)   根據(jù)方法名和參數(shù)矗积,返回一個具體的方法(不分public和非public屬性)
Method[] getDeclaredMethods()    返回該類中的所有的方法數(shù)組(不分public和非public屬性)

通過反射生成并操作對象代碼實(shí)例:

package com.wechat.management.reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class TestRefFieldAndMethod {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        Class c1 = Class.forName("com.wechat.management.reflection.UserDTO");
        //1、獲得類的名字--->獲得包名+類名
        System.out.println(c1.getName());//com.wechat.management.reflection.UserDTO
        //2奶栖、獲得類的簡單名字-->獲得類名
        System.out.println(c1.getSimpleName());//User

        System.out.println("=======================");
        //3匹表、獲得類的屬性
        //3.1 獲得public的屬性
        Field[] fields = c1.getFields();//只能找到public的屬性

        //3.2  能夠找到所有的屬性
        Field[] fields1 = c1.getDeclaredFields();
        for (Field field: fields1) {
            System.out.println(field);
        }

        /**
         * private int com.wechat.management.reflection.UserDTO.id
         * private java.lang.String com.wechat.management.reflection.UserDTO.name
         * private int com.wechat.management.reflection.UserDTO.age
         */
        //3.3门坷、獲得指定的屬性
        Field name = c1.getDeclaredField("name");
        System.out.println(name);//private java.lang.String com.wechat.management.reflection.UserDTO.name

        //4宣鄙、獲得類的方法
        System.out.println("====================================");
        Method[] methods = c1.getMethods();//獲得本類及其父類的全部public方法
        for (Method method : methods) {
            System.out.println("c1.getMethods():"+method);
        }
        Method[] methods1 = c1.getDeclaredMethods();//獲得本類的全部方法
        for (Method method : methods1) {
            System.out.println("c1.getDeclaredMethods():"+method);
        }
        //獲取指定的方法   重載,所以要添加參數(shù)
        Method getName = c1.getMethod("getName", null);
        System.out.println(getName);//public java.lang.String com.wechat.management.reflection.UserDTO.getName()
        Method setName = c1.getMethod("setName", String.class);
        System.out.println(setName);//public void com.wechat.management.reflection.UserDTO.setName(java.lang.String)

        //5默蚌、獲取指定的構(gòu)造器
        System.out.println("=================================");
        Constructor[] constructors = c1.getConstructors();//獲取public
        for (Constructor constructor : constructors) {
            System.out.println("c1.getConstructors():"+constructor);
        }
        Constructor[] constructors1 = c1.getDeclaredConstructors();//獲取所有的構(gòu)造器
        for (Constructor constructor : constructors1) {
            System.out.println("c1.getDeclaredConstructors():"+constructor);
        }

        //獲取指定的構(gòu)造器
        Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
        System.out.println("獲取指定的構(gòu)造器"+declaredConstructor);//獲取指定的構(gòu)造器public com.wechat.management.reflection.UserDTO(int,java.lang.String,int)
    }
}


class UserDTO {

    private int id;
    private String name;
    private int age;

    public UserDTO() {
    }

    public UserDTO(String name, int id, int age) {
        super();
        this.name = name;
        this.id = id;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User [name=" + name + ", id=" + id + ", age=" + age + "]";
    }
}

通過反射調(diào)用對象方法

public class TestInvoke {

    public String invokeMethod() {
        System.out.println("invokeMethod已執(zhí)行冻晤!");
        return "invokeMethod已執(zhí)行!";
    }
    
    public static void main(String[] args) throws Exception {  
        //1.通過反射獲取Class對象
        Class stuClass = Class.forName("com.wechat.management.reflection.TestInvoke");//"com.wechat.management.reflection.TestInvoke"
        //2.獲取invokeMethod()方法
        Method method = stuClass.getMethod("invokeMethod");
        //3.創(chuàng)建對象
        TestInvoke testInvoke = (TestInvoke) stuClass.newInstance();
        //4.調(diào)用invokeMethod()方法
        String retrunStr = (String) method.invoke(testInvoke, null);
        System.out.println("獲取方法執(zhí)行后的返回值:"+retrunStr);
    }
}

通過反射執(zhí)行類方法的步驟:

  1. 通過反射獲取Class對象
  2. 通過getMethod()指定方法名獲取方法
  3. 通過反射獲取的Class類創(chuàng)建實(shí)例對象
  4. 通過invoke()執(zhí)行指定方法

反射與泛型

Java采用泛型擦除的機(jī)制來引入泛型绸吸,Java中的泛型僅僅是給編譯器javac使用的鼻弧,確保數(shù)據(jù)的安全性和免去強(qiáng)制類型轉(zhuǎn)換的問題,但是锦茁,一旦編譯完成攘轩,所有和泛型有關(guān)的類型全部擦除。

通過反射越過泛型檢查:

import java.lang.reflect.Method;
import java.util.ArrayList;

public class InvokeDemo {

    public static void main(String[] args) throws Exception {
        ArrayList<Integer> strList = new ArrayList<>();
        strList.add(100);
        strList.add(200);
        
        //獲取ArrayList的Class對象码俩,反向的調(diào)用add()方法度帮,添加數(shù)據(jù)
        Class listClass = strList.getClass(); //得到 strList 對象的字節(jié)碼 對象
        //獲取add()方法
        Method method = listClass.getMethod("add", Object.class);
        //調(diào)用add()方法
        method.invoke(strList, "數(shù)字");

        //遍歷集合
        for (Object obj : strList) {
            System.out.println(obj);
        }
    }
}

執(zhí)行結(jié)果:

100
200
數(shù)字

為了通過反射操作泛型代表的類型,Java新增了ParameterizedType稿存,GenericArrayType笨篷,TypeVariableWildcardType幾種類型來代表不能被歸一到Class類中的類型但是又和原始類型齊名的類型。

類型 說明
ParameterizedType 表示一種參數(shù)化類型瓣履,比如Collection< String >
GenericArrayType 表示一種元素類型是參數(shù)化類型或者類型變量的數(shù)組類型
TypeVariable 是各種類型變量的公共父接口
WildcardType 代表一種通配符類型表達(dá)式
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
public class TestReflectGen {
    /**
     * 通過泛型傳參
     * @param map
     * @param list
     */
    public void test01(Map<String,User> map, List<Integer> list){
        System.out.println("test01");

    }

    /**
     * 通過泛型返回值
     * @return
     */
    public Map<String,User> test02(){
        System.out.println("test02");
        return null;
    }

    public static void main(String[] args) throws NoSuchMethodException {
        //獲得參數(shù)類型
        Method method = Test11.class.getMethod("test01", Map.class, List.class);
        //獲取參數(shù)類型  即Map和 List
        Type[] genericParameterTypes = method.getGenericParameterTypes();
        for (Type genericParameterType : genericParameterTypes) {
            System.out.println("1:"+genericParameterType);

            //判斷genericParameterType參數(shù)類型 是否屬于 ParameterizedType 參數(shù)化類型
            if (genericParameterType instanceof ParameterizedType){
                //如果屬于參數(shù)化類型率翅,獲得他的真實(shí)類型 getActualTypeArguments
                Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();

                //再次輸出真實(shí)的泛型信息
                for (Type actualTypeArgument : actualTypeArguments) {
                    System.out.println("2:"+actualTypeArgument);
                }
            }
        }
        
        
        //獲得返回值類型
        method = Test11.class.getMethod("test02",null);
        Type genericReturnType = method.getGenericReturnType();
        if (genericReturnType instanceof ParameterizedType){
            //如果genericReturnType返回值類型屬于參數(shù)化類型,獲得他的真實(shí)類型 getActualTypeArguments
            Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
            
            //再次輸出真實(shí)的泛型信息
            for (Type actualTypeArgument : actualTypeArguments) {
                System.out.println("3:"+actualTypeArgument);
            }
        }
    }
}

反射與注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;

public class TestReflectAnnotation {
    public static void main(String[] args) throws Exception {
        TestAccountAnnotation testAccountAnnotation = new TestAccountAnnotation();
        Class<?> class1 = TestAccountAnnotation.class;
        Method method = class1.getMethod("show", String.class, int.class, String.class);
        Account annotation = method.getAnnotation(Account.class);
        String name = annotation.name();
        int age = annotation.age();
        String gender = annotation.gender();
        method.invoke(testAccountAnnotation, name, age, gender);
    }
}

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface Account {
    String name();

    int age() default 18;

    String gender();
}

class TestAccountAnnotation {

    @Account(name = "法外狂徒", gender = "男")
    public void show(String name, int age, String gen) {
        System.out.println(name);
        System.out.println(age);
        System.out.println(gen);
    }

}

執(zhí)行結(jié)果:

法外狂徒
18
男
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末袖迎,一起剝皮案震驚了整個濱河市冕臭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌瓢棒,老刑警劉巖浴韭,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異脯宿,居然都是意外死亡念颈,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進(jìn)店門连霉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來榴芳,“玉大人,你說我怎么就攤上這事跺撼】吒校” “怎么了?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵歉井,是天一觀的道長柿祈。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么躏嚎? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任蜜自,我火速辦了婚禮,結(jié)果婚禮上卢佣,老公的妹妹穿的比我還像新娘重荠。我一直安慰自己,他們只是感情好虚茶,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布戈鲁。 她就那樣靜靜地躺著,像睡著了一般嘹叫。 火紅的嫁衣襯著肌膚如雪婆殿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天罩扇,我揣著相機(jī)與錄音鸣皂,去河邊找鬼。 笑死暮蹂,一個胖子當(dāng)著我的面吹牛寞缝,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播仰泻,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼荆陆,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了集侯?” 一聲冷哼從身側(cè)響起被啼,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎棠枉,沒想到半個月后浓体,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡辈讶,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年命浴,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贱除。...
    茶點(diǎn)故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡生闲,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出月幌,到底是詐尸還是另有隱情碍讯,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布扯躺,位于F島的核電站捉兴,受9級特大地震影響蝎困,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜倍啥,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一难衰、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧逗栽,春花似錦、人聲如沸失暂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽弟塞。三九已至凭峡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間决记,已是汗流浹背摧冀。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留系宫,地道東北人索昂。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像扩借,于是被迫代替她去往敵國和親椒惨。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評論 2 355

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