成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

Java反射機(jī)制實(shí)例分析

這篇“Java反射機(jī)制實(shí)例分析”文章的知識(shí)點(diǎn)大部分人都不太理解,所以小編給大家總結(jié)了以下內(nèi)容,內(nèi)容詳細(xì),步驟清晰,具有一定的借鑒價(jià)值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來(lái)看看這篇“Java反射機(jī)制實(shí)例分析”文章吧。

讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來(lái)自于我們對(duì)這個(gè)行業(yè)的熱愛(ài)。我們立志把好的技術(shù)通過(guò)有效、簡(jiǎn)單的方式提供給客戶,將通過(guò)不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:域名與空間、雅安服務(wù)器托管、營(yíng)銷(xiāo)軟件、網(wǎng)站建設(shè)、吉利網(wǎng)站維護(hù)、網(wǎng)站推廣。

Java反射機(jī)制實(shí)例分析

Java反射機(jī)制

Java的反射(reflection)機(jī)制是指在程序的運(yùn)行狀態(tài)中,可以構(gòu)造任意一個(gè)類(lèi)的對(duì)象,可以了解任意一個(gè)對(duì)象所屬的類(lèi),可以了解任意一個(gè)類(lèi)的成員變量和方法,可以調(diào)用任意一個(gè)對(duì)象的屬性和方法。這種動(dòng)態(tài)獲取程序信息以及動(dòng)態(tài)調(diào)用對(duì)象的功能稱(chēng)為Java語(yǔ)言的反射機(jī)制。反射被視為動(dòng)態(tài)語(yǔ)言的關(guān)鍵。

我不太擅長(zhǎng)文字表達(dá),還是上圖操作把

不用反射機(jī)制的例子

//定義一個(gè)animals接口interface animals {
    public abstract void print();}//定義類(lèi)來(lái)實(shí)現(xiàn)animals接口的抽象方法class Dog implements animals {
    public void print() {
        System.out.println("Dog");
    }}class Cat implements animals {
    public void print() {
        System.out.println("Cat");
    }}// 構(gòu)造一個(gè)zoo類(lèi)// 之后如果我們?cè)谔砑悠渌膶?shí)例的時(shí)候只需要修改zoo類(lèi)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類(lèi)尋找對(duì)應(yīng)的類(lèi)來(lái)實(shí)現(xiàn)接口
        animals a=zoo.getInstance("Cat");
        if(a!=null)
            a.print();
    }}

這時(shí)候添加動(dòng)物,只需要

  • 添加類(lèi)

  • 修改zoo

  • 修改main函數(shù)的動(dòng)物類(lèi)

把上面修改為反射機(jī)制

//定義一個(gè)animals接口interface animals {
    public abstract void print();}//定義類(lèi)來(lái)實(shí)現(xiàn)animals接口的抽象方法class Dog implements animals {
    public void print() {
        System.out.println("Dog");
    }}class Cat implements animals {
    public void print() {
        System.out.println("Cat");
    }}// 構(gòu)造一個(gè)zoo類(lèi)// 之后如果我們?cè)谔砑悠渌膶?shí)例的時(shí)候只需要修改zoo類(lèi)class zoo {

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

這時(shí)候添加動(dòng)物只需要

  • 添加類(lèi)

  • 修改main函數(shù)的動(dòng)物類(lèi)

省了一步,傳入類(lèi)名可控,發(fā)現(xiàn)好像是存在的類(lèi)都可以調(diào)

反射機(jī)制方法

我們用的最多的可能是

  • forName(調(diào)用類(lèi))

  • getMethod(調(diào)用類(lèi)下方法)

  • invoke(執(zhí)行)

  • newInstance(實(shí)例化對(duì)象)

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

下面我們用反射機(jī)制來(lái)彈出計(jì)算機(jī)(calc)或者記事本(notepad)

由于彈出計(jì)算機(jī)有點(diǎn)多這次我就彈記事本把,總而言之,能彈出來(lái)就很美妙

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

Java反射機(jī)制實(shí)例分析
我們看下getRuntime函數(shù)
Java反射機(jī)制實(shí)例分析
得知,該函數(shù)是Runtime類(lèi)獲取對(duì)象的方式,個(gè)人感覺(jué)是每用一次就調(diào)一次比較麻煩,為了不調(diào)用一次建立一個(gè)對(duì)象所以封裝成了函數(shù)

類(lèi)對(duì)象獲取方式

  • Class.forName(類(lèi)名獲?。?/p>

  • zoo.class(已經(jīng)加載過(guò)的類(lèi))

  • obj.class(實(shí)例)
    Java反射機(jī)制實(shí)例分析

類(lèi)初始化

修改zoo類(lèi),增加初始?jí)K、靜態(tài)初始?jí)K、和構(gòu)造函數(shù)

class zoo {
    //初始?jí)K
    {
        System.out.println("1  " + this.getClass());
    }

    //靜態(tài)初始?jí)K
    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尋找類(lèi)名,并用newInstance實(shí)例化類(lèi)似于new
            a = (animals) Class.forName(className).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return a;
    }}

類(lèi)初始化執(zhí)行順序:靜態(tài)初始?jí)K
Java反射機(jī)制實(shí)例分析
類(lèi)實(shí)例化執(zhí)行順序:靜態(tài)初始?jí)K - > 初始?jí)K - > 構(gòu)造函數(shù)
Java反射機(jī)制實(shí)例分析
由此得知,類(lèi)初始化和類(lèi)實(shí)例化不一樣

接下來(lái)增加zoo1類(lèi)繼承zoo類(lèi)

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

    //靜態(tài)初始?jí)K
    static {
        System.out.println("12  " + zoo.class);
    }

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

子類(lèi)初始化順序:父類(lèi)靜態(tài)初始化塊 - > 子類(lèi)靜態(tài)初始化塊
Java反射機(jī)制實(shí)例分析
子類(lèi)實(shí)例化順序:父類(lèi)靜態(tài)初始化塊 - > 子類(lèi)靜態(tài)初始化塊 - > 父類(lèi)初始化塊 - > 父類(lèi)構(gòu)造函數(shù) - > 子類(lèi)初始化塊 - >子類(lèi)構(gòu)造函數(shù)
Java反射機(jī)制實(shí)例分析
以上可以得知,當(dāng)使用Class.forName時(shí),且類(lèi)靜態(tài)初始化塊可控,可以執(zhí)行任意代碼

調(diào)用內(nèi)部類(lèi)

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

getMethod

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

invoke

靜態(tài)和動(dòng)態(tài)方法的區(qū)別
Java反射機(jī)制實(shí)例分析

invoke方法在getMethod類(lèi)下,作用時(shí)傳遞參數(shù),執(zhí)行方法
public Object invoke(Object obj, Object… args)
第一個(gè)參數(shù)是getMethod獲取的方法的類(lèi)對(duì)象(如果方法是靜態(tài)方法則傳類(lèi))
獲取exec函數(shù)的類(lèi)對(duì)象
Class.forName(“java.lang.Runtime”).getMethod(“getRuntime”).invoke(Class.forName(“java.lang.Runtime”))
由于getRuntime是靜態(tài)方法,所以傳類(lèi)
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反射機(jī)制實(shí)例分析

指定構(gòu)造方法生成實(shí)例

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

getConsturctor(函數(shù)可以選定指定接口格式的構(gòu)造函數(shù)(由于構(gòu)造函數(shù)也可以根據(jù)參數(shù)來(lái)進(jìn)行重載)
選定后我們可以通過(guò)newInstance(),并傳入構(gòu)造函數(shù)的參數(shù)執(zhí)行構(gòu)造函數(shù)

ProcessBuilder類(lèi)有兩個(gè)構(gòu)造函數(shù)

  • public ProcessBuilder(String… command)(String…變長(zhǎng)的字符串?dāng)?shù)組String[].class)

  • public ProcessBuilder(List command)

分別使用構(gòu)造方法

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

    {“notepad”}})

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

執(zhí)行完構(gòu)造方法實(shí)例后,在進(jìn)行強(qiáng)制轉(zhuǎn)化使用start函數(shù)即可

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

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

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

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

在這行打斷點(diǎn)調(diào)試
Java反射機(jī)制實(shí)例分析
我們傳的是一個(gè)字符串?dāng)?shù)組到了實(shí)例化的時(shí)候變成了一個(gè)字符串,再看看另一個(gè)構(gòu)造函數(shù)(List)

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

依舊還是這行打斷點(diǎn)

Java反射機(jī)制實(shí)例分析
由此可知,List傳入時(shí)會(huì)被當(dāng)作Object的第一項(xiàng),而String[]會(huì)被當(dāng)做Object,所以多加一層[]{}

執(zhí)行私有方法

通過(guò)函數(shù)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");

以上就是關(guān)于“Java反射機(jī)制實(shí)例分析”這篇文章的內(nèi)容,相信大家都有了一定的了解,希望小編分享的內(nèi)容對(duì)大家有幫助,若想了解更多相關(guān)的知識(shí)內(nèi)容,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

本文名稱(chēng):Java反射機(jī)制實(shí)例分析
網(wǎng)頁(yè)鏈接:http://jinyejixie.com/article48/ijgchp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供軟件開(kāi)發(fā)、手機(jī)網(wǎng)站建設(shè)、品牌網(wǎng)站設(shè)計(jì)、商城網(wǎng)站、Google、網(wǎng)站導(dǎo)航

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)
青川县| 海门市| 尚义县| 辽阳市| 灵寿县| 临猗县| 成安县| 麻江县| 黑水县| 保定市| 万盛区| 抚宁县| 塔河县| 桂东县| 高陵县| 牙克石市| 冕宁县| 延安市| 天气| 巨鹿县| 武山县| 河间市| 托里县| 昌宁县| 泌阳县| 缙云县| 景谷| 元朗区| 江安县| 菏泽市| 仙游县| 西吉县| 百色市| 萝北县| 大姚县| 平泉县| 阜宁县| 成都市| 娱乐| 明溪县| 平舆县|