Java學(xué)習(xí):反射的應(yīng)用場景和解析方法

提到j(luò)ava語言的高級(jí)特性,反射絕對(duì)是Top1級(jí)別的,在大量開源框架中的應(yīng)用范例比比皆是,那么需要了解清楚反射到底是什么?為什么要使用反射?如何使用反射?(what,why,how)

什么是反射?

正常場景下,java從源碼到運(yùn)行有3個(gè)階段:
source class runtime

反射提供的是runtime階段獲取類的class實(shí)例、方法、屬性、注解,并且能夠調(diào)用類的方法的途徑,這種動(dòng)態(tài)獲取類信息和調(diào)用類方法的機(jī)制被稱之為反射

為什么要使用反射?

正常的實(shí)例化一個(gè)對(duì)象

ClassA objA = new ClassA();
objA.sayHello();

通過反射去實(shí)例化一個(gè)對(duì)象

Class objA  = ClassA.class;
Method method = objA.getMethod("sayHello");
method.invoke(objA.newInstance());

在source階段實(shí)際上二者并無任何區(qū)別,反射也沒有體現(xiàn)出任何的優(yōu)勢,那么任何一個(gè)java開發(fā)人員必然會(huì)問為什么要使用反射?
反射的重點(diǎn)在于runtime階段的獲取類信息和調(diào)用類方法,那么當(dāng)你的編碼過程中中有“部分信息是source階段不清晰,需要在runtime階段動(dòng)態(tài)臨時(shí)加載”這種場景,反射就可以派上用場了

我們考慮幾個(gè)編碼場景:
1、編碼階段不知道需要實(shí)例化的類名是哪個(gè),需要在runtime從配置文件中加載:

Class clazz = class.forName("xxx.xxx.xxx")
clazz.newInstance();

2、在runtime階段,需要臨時(shí)訪問類的某個(gè)私有屬性

ClassA objA = new ClassA();
Field xxx = objA.getClass().getDeclaredField("xxx")
xxx.setAccessible(true);

所以,反射的優(yōu)點(diǎn)在于“有些編碼需求在source階段無法實(shí)現(xiàn),只能在runtime階段通過反射實(shí)現(xiàn)”,而非“source階段正常編碼方式能解決的,反射的方式能解決的更好”,所以比較反射和正常編碼方式的優(yōu)劣是沒有意義的,反射解決的是正常編碼無法解決的編碼場景,如果正常編碼方式可以解決的,強(qiáng)行使用反射反而是毫無意義的,編碼不是為了show技巧。

反射應(yīng)用范例代碼

實(shí)現(xiàn)對(duì)類或者對(duì)象的構(gòu)造器、方法、屬性、注解的獲取和操作,具體作用見代碼中的注釋描述

public class ReflectionHelper {

    /**
     * Reflection Test Code
     *
     * @param args
     */
    public static void main(String[] args) {
        SSHClient sshClient = new SSHClient();

        // 獲取class名稱
        System.out.println("01-----獲取class名稱-----");
        System.out.println(sshClient.getClass().getName());
        System.out.println(sshClient.getClass().getSimpleName());
        System.out.println(sshClient.getClass().getTypeName());

        Class<?> clazz1 = null;
        Class<?> clazz2 = null;
        Class<?> clazz3 = null;

        // 獲取對(duì)象或者類的Class實(shí)例
        try {
            clazz1 = Class.forName(sshClient.getClass().getName());
            clazz2 = sshClient.getClass();
            clazz3 = ReflectionUtils.class;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        // 獲取類的構(gòu)造函數(shù),用構(gòu)造函數(shù)實(shí)例一個(gè)對(duì)象
        for (Constructor<?> clazz1Cstor : clazz1.getConstructors()) {
            System.out.println(clazz1Cstor.getName());
            try {
                SSHClient client1 = (SSHClient) clazz1.newInstance();
                SSHClient client2 = (SSHClient) clazz1Cstor.newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }

        }

        // 獲取類定義的方法、屬性
        System.out.println("02-----獲取類定義的方法、屬性-----");
        try {
            SSHClient client = (SSHClient) clazz1.newInstance();
            Method setHostMethod = clazz1.getDeclaredMethod("setHost", String.class);
            setHostMethod.invoke(client, "111");

            Field field = client.getClass().getDeclaredField("host");
            field.setAccessible(true);
            System.out.println(field.get(client));
            field.set(client,"a new host");
            System.out.println(field.get(client));
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }

        // 獲取類的注解
        System.out.println("03-----獲取類使用的注解-----");
        for (Annotation annotation : clazz1.getAnnotations()) {
            System.out.println(annotation.getClass().getName());
            System.out.println(annotation.toString());
            System.out.println(annotation.annotationType());
        }
    }
}

運(yùn)行結(jié)果:


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,544評(píng)論 19 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,954評(píng)論 25 709
  • 那天突然看到一個(gè)文章標(biāo)題里的這兩個(gè)詞,心里恍惚了一下。記得有個(gè)好朋友的名字就是叫做差不多先生。 我記得小的時(shí)候,童...
    孫大貓閱讀 753評(píng)論 4 5
  • 1.選擇圖片獲取方式 對(duì)圖片尺寸進(jìn)行壓縮 保存圖片至沙盒
    Heikki_閱讀 622評(píng)論 0 2
  • 新建一個(gè)test.swift后綴名的文件,寫下如下內(nèi)容 然后到終端輸入chmod +x ./test.swift ...
    cocoaroger閱讀 1,332評(píng)論 2 1

友情鏈接更多精彩內(nèi)容