中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java反射機制實例分析

發布時間:2022-03-04 09:39:05 來源:億速云 閱讀:126 作者:iii 欄目:編程語言

這篇“Java反射機制實例分析”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“Java反射機制實例分析”文章吧。

Java反射機制實例分析


Java反射機制

Java的反射(reflection)機制是指在程序的運行狀態中,可以構造任意一個類的對象,可以了解任意一個對象所屬的類,可以了解任意一個類的成員變量和方法,可以調用任意一個對象的屬性和方法。這種動態獲取程序信息以及動態調用對象的功能稱為Java語言的反射機制。反射被視為動態語言的關鍵。

我不太擅長文字表達,還是上圖操作把

不用反射機制的例子

//定義一個animals接口interface animals {
    public abstract void print();}//定義類來實現animals接口的抽象方法class Dog implements animals {
    public void print() {
        System.out.println("Dog");
    }}class Cat implements animals {
    public void print() {
        System.out.println("Cat");
    }}// 構造一個zoo類// 之后如果我們在添加其他的實例的時候只需要修改zoo類class zoo {

    public static animals getInstance(String animalsName) {
        animals a = null;
        if ("Dog".equals(animalsName)) {
            a = new Dog();
        }
        if ("Cat".equals(animalsName)) {
            a = new Cat();
        }
        return a;
    }}public class reflection {
    public static void main(String[] args) {
        //借助zoo類尋找對應的類來實現接口
        animals a=zoo.getInstance("Cat");
        if(a!=null)
            a.print();
    }}

這時候添加動物,只需要

  • 添加類

  • 修改zoo

  • 修改main函數的動物類

把上面修改為反射機制

//定義一個animals接口interface animals {
    public abstract void print();}//定義類來實現animals接口的抽象方法class Dog implements animals {
    public void print() {
        System.out.println("Dog");
    }}class Cat implements animals {
    public void print() {
        System.out.println("Cat");
    }}// 構造一個zoo類// 之后如果我們在添加其他的實例的時候只需要修改zoo類class zoo {

    public static animals getInstance(String className) {
        animals a = null;
        try {
            //借助Class.forName尋找類名,并用newInstance實例化類似于new
            a = (animals) Class.forName(className).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return a;
    }}public class reflection {
    public static void main(String[] args) {
        //借助zoo類尋找對應的類來實現接口(classname為當前包名加類名)
        animals a = zoo.getInstance("com.cc1.Dog");
        if (a != null)
            a.print();
    }}

這時候添加動物只需要

  • 添加類

  • 修改main函數的動物類

省了一步,傳入類名可控,發現好像是存在的類都可以調

反射機制方法

我們用的最多的可能是

  • forName(調用類)

  • getMethod(調用類下方法)

  • invoke(執行)

  • newInstance(實例化對象)

Class.forName(className).getMethod(methodName).invoke(Class.forName(className).newInstance());

下面我們用反射機制來彈出計算機(calc)或者記事本(notepad)

由于彈出計算機有點多這次我就彈記事本把,總而言之,能彈出來就很美妙

Runtime.getRuntime().exec("notepad");

Java反射機制實例分析
我們看下getRuntime函數
Java反射機制實例分析
得知,該函數是Runtime類獲取對象的方式,個人感覺是每用一次就調一次比較麻煩,為了不調用一次建立一個對象所以封裝成了函數

類對象獲取方式

  • Class.forName(類名獲取)

  • zoo.class(已經加載過的類)

  • obj.class(實例)
    Java反射機制實例分析

類初始化

修改zoo類,增加初始塊、靜態初始塊、和構造函數

class zoo {
    //初始塊
    {
        System.out.println("1  " + this.getClass());
    }

    //靜態初始塊
    static {
        System.out.println("2  " + zoo.class);
    }

    public zoo() {
        System.out.println("3  " + this.getClass());
    }

    public static animals getInstance(String className) {
        animals a = null;
        try {
            //借助Class.forName尋找類名,并用newInstance實例化類似于new
            a = (animals) Class.forName(className).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return a;
    }}

類初始化執行順序:靜態初始塊
Java反射機制實例分析
類實例化執行順序:靜態初始塊 - > 初始塊 - > 構造函數
Java反射機制實例分析
由此得知,類初始化和類實例化不一樣

接下來增加zoo1類繼承zoo類

class zoo1 extends zoo{
    //初始塊
    {
        System.out.println("11  " + this.getClass());
    }

    //靜態初始塊
    static {
        System.out.println("12  " + zoo.class);
    }

    public zoo1() {
        System.out.println("13  " + this.getClass());
    }}

子類初始化順序:父類靜態初始化塊 - > 子類靜態初始化塊
Java反射機制實例分析
子類實例化順序:父類靜態初始化塊 - > 子類靜態初始化塊 - > 父類初始化塊 - > 父類構造函數 - > 子類初始化塊 - >子類構造函數
Java反射機制實例分析
以上可以得知,當使用Class.forName時,且類靜態初始化塊可控,可以執行任意代碼

調用內部類

Class.forName(“java.lang.Runtime”)來獲取類(java.lang.Runtime是Runtime類的完整路徑)

getMethod

getMethod 的作用是通過反射獲取類的某個特定的公有方法。
java支持類重載,但不能僅通過一個函數名確定一個函數,所以在調用getMethod時,需要傳給它方法的參數類型列表
Class.forName(“java.lang.Runtime”).getMethod(“exec”, String.class)

invoke

靜態和動態方法的區別
Java反射機制實例分析

invoke方法在getMethod類下,作用時傳遞參數,執行方法
public Object invoke(Object obj, Object… args)
第一個參數是getMethod獲取的方法的類對象(如果方法是靜態方法則傳類)
獲取exec函數的類對象
Class.forName(“java.lang.Runtime”).getMethod(“getRuntime”).invoke(Class.forName(“java.lang.Runtime”))
由于getRuntime是靜態方法,所以傳類
invoke(Class.forName(“java.lang.Runtime”).getMethod(“getRuntime”).invoke(Class.forName(“java.lang.Runtime”)),“calc.exe”)

最后我們合并一下

Class.forName("java.lang.Runtime").
                getMethod("exec", String.class).
                invoke(Class.forName("java.lang.Runtime").getMethod("getRuntime").invoke(Class.forName("java.lang.Runtime")), "notepad");

Java反射機制實例分析

指定構造方法生成實例

String str="notepad";ProcessBuilder pb = new ProcessBuilder(str);pb.start();

getConsturctor(函數可以選定指定接口格式的構造函數(由于構造函數也可以根據參數來進行重載)
選定后我們可以通過newInstance(),并傳入構造函數的參數執行構造函數

ProcessBuilder類有兩個構造函數

  • public ProcessBuilder(String… command)(String…變長的字符串數組String[].class)

  • public ProcessBuilder(List command)

分別使用構造方法

  • Class.forName(“java.lang.ProcessBuilder”).getConstructor(String[].class).newInstance(new String[][]{

    {“notepad”}})

  • Class.forName(“java.lang.ProcessBuilder”).getConstructor(List.class).newInstance(Arrays.asList(“notepad”))

執行完構造方法實例后,在進行強制轉化使用start函數即可

( (ProcessBuilder) Class.forName(“java.lang.ProcessBuilder”).getConstructor(List.class).newInstance(Arrays.asList(“notepad”))).start();

實際中,肯定用不了,哪有這么好的事,還是接著反射把

Class.forName(“java.lang.ProcessBuilder”).getMethod(“start”).invoke(clazz.getConstructor(List.class).newInstance(Arrays.asList(“notepad”)));
Java反射機制實例分析
這里可能有人會好奇我寫的里那的另一個構造函數,String…command這個傳參為什么用new String[][]{{“notepad”}},不應該是new String[]{“notepad”},現在用應該的

((ProcessBuilder) Class.forName(“java.lang.ProcessBuilder”).getConstructor(String[].class).newInstance(new String[]{“notepad”})).start();

在這行打斷點調試
Java反射機制實例分析
我們傳的是一個字符串數組到了實例化的時候變成了一個字符串,再看看另一個構造函數(List)

( (ProcessBuilder) Class.forName(“java.lang.ProcessBuilder”).getConstructor(List.class).newInstance(Arrays.asList(“notepad”))).start();

依舊還是這行打斷點

Java反射機制實例分析
由此可知,List傳入時會被當作Object的第一項,而String[]會被當做Object,所以多加一層[]{}

執行私有方法

通過函數getDeclaredConstructor獲取私有方法,再利用setAccessible(true)打破私有方法限制

Class cls = Class.forName("java.lang.Runtime"); 
Constructor m = cls.getDeclaredConstructor();
 m.setAccessible(true); 
 cls.getMethod("exec", String.class).invoke(m.newInstance(), "notepad");

以上就是關于“Java反射機制實例分析”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

德钦县| 舒兰市| 丰原市| 汝州市| 武邑县| 普安县| 鹿邑县| 湘西| 临江市| 平谷区| 文成县| 韶关市| 洮南市| 文安县| 南投市| 浦江县| 苗栗县| 大余县| 宜君县| 徐闻县| 平罗县| 如东县| 德令哈市| 西昌市| 奉贤区| 璧山县| 渭南市| 玉田县| 榆树市| 鹰潭市| 凤台县| 伊金霍洛旗| 泰兴市| 开化县| 青冈县| 陈巴尔虎旗| 乡宁县| 峨眉山市| 自贡市| 无为县| 娄烦县|