反射機(jī)制案例

在Java中简烤,可以利用反射獲取指定類型的公有/私有屬性、方法距糖,生成該類的實(shí)例對(duì)象娶吞,并調(diào)用該對(duì)象的方法垒迂。

以下反射相關(guān)的幾個(gè)案例:
ClassDemo1.java

package one;

public class ClassDemo1 {
    public static void main(String[] args) {
        //Foo的實(shí)例對(duì)象
        Foo foo1 = new Foo();
        
        //任何一個(gè)類都是Class類的實(shí)例對(duì)象,有三種表示方法
        //第一種表示方式-->任何一個(gè)類都有一個(gè)隱含的靜態(tài)成員變量class
        Class c1 = Foo.class;
        
        //第二種表達(dá)方式,已知該類的對(duì)象通過個(gè)體Class方法
        Class c2 = foo1.getClass();
        
        /*
         * c1妒蛇,c2表示了父類的類類型(class type)
         * 萬事萬物皆對(duì)象
         * 類也是對(duì)象机断,是Class類的實(shí)例對(duì)象
         * 這個(gè)對(duì)象我們稱為該類的類類型
         */
        
        //不管c1或者c2都代表了Foo類的類類型楷拳,一個(gè)類只可能是Class類的一個(gè)實(shí)例對(duì)象
        System.out.println(c1 == c2);
        
        //第三種表達(dá)方式
        Class c3 = null;
        try {
            c3 = Class.forName("one.Foo");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        
        System.out.println(c2 == c3);
        
        //我們完全可以通過類的類類型創(chuàng)建該類的對(duì)象-->通過c1或c2或c3創(chuàng)建Foo的實(shí)例
        try {
            Foo foo = (Foo)c1.newInstance();//需要有無參數(shù)的構(gòu)造方法
            foo.print();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

class Foo {
    void print() {
        System.out.println("hahahaha");
    }
}
ClassDemo1運(yùn)行結(jié)果

ClassDemo2.java

package one;

public class ClassDemo2 {
    public static void main(String[] args) {
        Class c1 = int.class;//int的類類型
        Class c2 = String.class;//String的類類型
        Class c3 = double.class;
        Class c4 = Double.class;
        Class c5 = void.class;
        
        System.out.println(c1.getName());
        System.out.println(c2.getName());
        System.out.println(c2.getSimpleName());//不含包名的類名稱
    }
}
ClassDemo2運(yùn)行結(jié)果

ClassUtil.java

package one;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class ClassUtil {
    /**
     * 打印類的信息,包括類的成員函數(shù)
     * @param obj 對(duì)象類
     */
    public static void printClassMethodMessage(Object obj) {
        //要獲取類的信息 首先要獲取類的類型
        Class c = obj.getClass();//傳遞的是哪個(gè)子類的對(duì)象吏奸,c就是該子類的類類型
        //獲取類的名稱
        System.out.println("類的名稱是:" + c.getName());
        /*
         * Method類欢揖,方法對(duì)象
         * 一個(gè)成員方法就是一個(gè)Method對(duì)象
         * getMethods()方法獲取的是所有的public的函數(shù),包括父類繼承來的
         * getDeclaredMethods()獲取的是所有該類自己聲明的方法奋蔚,不問訪問權(quán)限
         */
        Method[] ms = c.getMethods();//c.getDeclaredMethods();
        for (int i = 0; i < ms.length; i++) {
            //得到返回值類型的類類型
            Class returnType = ms[i].getReturnType();
            System.out.print(returnType.getName() + " ");
            //得到方法名
            System.out.print(ms[i].getName() + "(");
            //獲取參數(shù)類型-->得到的是參數(shù)列表的類型的類類型
            Class[] paramTypes = ms[i].getParameterTypes();
            for (Class class1 : paramTypes) {
                //System.out.print(class1.getName() + ",");
                System.out.print(class1.getSimpleName() + ",");
            }
            
            System.out.println(")");
        }
    }

    /**
     * 獲取成員變量的信息
     * @param obj 對(duì)象類
     */
    public static void printFieldMessage(Object obj) {
        Class c = obj.getClass();
        /*
         * 成員變量也是對(duì)象
         * java.lang.reflect.Field
         * Field類封裝了關(guān)于成員變量的操作
         * getField()方法獲取的是所有的public的成員變量的信息
         * getDeclaredFields()獲取的是該類自己聲明的成員變量的信息她混,不管訪問權(quán)限
         */
        //Field[] fs = c.getFields();
        Field[] fs = c.getDeclaredFields();
        for (Field field : fs) {
            //得到成員變量的類類型
            Class fieldType = field.getType();
            String typeName = fieldType.getName();
            //得到成員變量的名稱
            String fieldName = field.getName();
            System.out.println(typeName + " " + fieldName);
        }
    }
    
    /**
     * 打印對(duì)象的構(gòu)造函數(shù)的信息
     * @param obj 對(duì)象類
     */
    public static void printConMessage(Object obj) {
        Class c = obj.getClass();
        /*
         * 構(gòu)造函數(shù)也是對(duì)象
         * java.lang.Constructor中封裝了構(gòu)造函數(shù)的信息
         * getConstructors()方法獲取的是所有的public的構(gòu)造函數(shù)的信息
         * getDeclaredConstructors()獲取的事該類自己聲明的構(gòu)造函數(shù)的信息,不管訪問權(quán)限
         */
        //Constructor[] cs = c.getConstructors();
        Constructor[] cs = c.getDeclaredConstructors();
        for (Constructor constructor : cs) {
            System.out.print(constructor.getName() + "(");
            //獲取構(gòu)造函數(shù)的參數(shù)列表-->得到參數(shù)列表的類類型
            Class[] paramTypes = constructor.getParameterTypes();
            for (Class class1 : paramTypes) {
                System.out.print(class1.getName() + ",");
            }
            System.out.println(")");
        }
    }
}

ClassDemo3.java

package one;

public class ClassDemo3 {
    package one;

public class ClassDemo3 {
    public static void main(String[] args) {
        String s = "hello";
        //打印該類方法信息
        ClassUtil.printClassMethodMessage(s);
        
        Integer n1 = 1;
        ClassUtil.printClassMethodMessage(n1);
    }
}
ClassDemo3運(yùn)行結(jié)果1

ClassDemo3運(yùn)行結(jié)果2

ClassDemo4.java

package one;

public class ClassDemo4 {
    public static void main(String[] args) {
        //打印該類成員變量信息
        ClassUtil.printFieldMessage(new Integer(1));
    }
}
ClassDemo4運(yùn)行結(jié)果

ClassDemo5.java

package one;

public class ClassDemo5 {
    public static void main(String[] args) {
        //打印構(gòu)造方法信息
        ClassUtil.printConMessage("hello");
        ClassUtil.printConMessage(new Integer(1));
    }
}
ClassDemo5運(yùn)行結(jié)果

MethodDemo1.java

package one;

import java.lang.reflect.Method;

public class MethodDemo1 {
    public static void main(String[] args) {
        //獲取print(int,int)方法 
        //1.要獲取一個(gè)方法泊碑,首先要獲取類的類類型
        A a1 = new A();
        Class c = a1.getClass();
        /*
         * 2.獲取方法 名稱和參數(shù)列表來決定
         * getMethod獲取的是public的方法
         * getDeclaredMethod獲取自己聲明的方法
         */
        try {
//          Method m = c.getMethod("print", new Class[]{int.class,int.class});
            //獲取print(int,int)方法坤按,其兩個(gè)參數(shù)都是int類型的
            Method m = c.getMethod("print", int.class,int.class);
            
            //方法的反射操作
            //a1.print(10,20);方法的反射操作是用m對(duì)象來進(jìn)行方法調(diào)用和a1.print調(diào)用的效果一樣
            //方法如果沒有返回值返回null,有返回值返回具體的返回值
            //Object o = m.invoke(a1,new Object[]{10,20});
            Object o = m.invoke(a1, 10,20); //執(zhí)行print(int,int)方法
            
            System.out.println("==========================");
            //獲取方法print(String,String)
            Method m1 = c.getMethod("print", String.class,String.class);
            //用方法進(jìn)行反射操作
            //a1.print("hello", "World");
            o = m1.invoke(a1, "hello","World"); //執(zhí)行print(String,String)
            
            System.out.println("===========================");
            //Method m2 = c.getMethod("print", new Class[]{});
            Method m2 = c.getMethod("print"); //獲取沒有參數(shù)的print()方法
            m2.invoke(a1); //執(zhí)行print方法
        } catch (Exception e) {
            e.printStackTrace();
        } 
    }
}

class A {
    public void print() {
        System.out.println("helloworld");
    }
    
    public void print(int a,int b) {
        System.out.println(a + b);
    }
    
    public void print(String a,String b) {
        System.out.println(a.toUpperCase() + "," + b.toLowerCase());
    }
}
MethodDemo1運(yùn)行結(jié)果

MethodDemo4.java

package one;

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

public class MethodDemo4 {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        
        ArrayList<String> list1 = new ArrayList<String>();
        list1.add("hello");
        //list1.add(1);錯(cuò)誤的
        Class c1 = list.getClass();
        Class c2 = list1.getClass();
        System.out.println(c1 == c2);
        //反射的操作都是編譯之后的操作
        
        /*
         * c1==c2結(jié)果返回true說明編譯之后的集合的泛型是去泛型化的
         * java中集合的泛型是防止錯(cuò)誤輸入的馒过,只在編譯階段有效
         * 繞過編譯就無效了
         * 驗(yàn)證:我們可以通過方法的反射來操作臭脓,繞過編譯
         */
        try {
            Method m = c2.getMethod("add", Object.class);
            m.invoke(list1, 100);//繞過變異操作就繞過了泛型
            System.out.println(list1);
            System.out.println(list1.size());
            //此時(shí)不能使用使用foreach遍歷,因?yàn)橛衖nt型
        } catch (Exception e) {
            e.printStackTrace();
        }
        
    }
}
MethodDemo4運(yùn)行結(jié)果

OfficeBetter.java

package one;

//new 對(duì)象名 創(chuàng)建出來的都是靜態(tài)加載類腹忽,編譯時(shí)所有可能用到的類必須存在来累,否則不能通過編譯
//動(dòng)態(tài)加載類Class.forName ,使用此方法編譯時(shí)只調(diào)用用到的類
public class OfficeBetter {
    public static void main(String[] args) {
        System.out.println(args[0]);
        try {
            Class c = Class.forName(args[0]);
            OfficeAble oa = (OfficeAble) c.newInstance();
            oa.print();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

interface OfficeAble {
    public void print();
}

class Word implements OfficeAble {
    public void print() {
        System.out.println("I am Word");
    }
}

class Excel implements OfficeAble {
    public void print() {
        System.out.println("I am Excel");
    }
}
OfficeBetter運(yùn)行結(jié)果
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末窘奏,一起剝皮案震驚了整個(gè)濱河市嘹锁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蔼夜,老刑警劉巖兼耀,帶你破解...
    沈念sama閱讀 217,907評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件压昼,死亡現(xiàn)場離奇詭異求冷,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)窍霞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門匠题,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人但金,你說我怎么就攤上這事韭山。” “怎么了冷溃?”我有些...
    開封第一講書人閱讀 164,298評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵钱磅,是天一觀的道長。 經(jīng)常有香客問我似枕,道長盖淡,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,586評(píng)論 1 293
  • 正文 為了忘掉前任凿歼,我火速辦了婚禮褪迟,結(jié)果婚禮上冗恨,老公的妹妹穿的比我還像新娘。我一直安慰自己味赃,他們只是感情好掀抹,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著心俗,像睡著了一般傲武。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上另凌,一...
    開封第一講書人閱讀 51,488評(píng)論 1 302
  • 那天谱轨,我揣著相機(jī)與錄音,去河邊找鬼吠谢。 笑死土童,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的工坊。 我是一名探鬼主播献汗,決...
    沈念sama閱讀 40,275評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼王污!你這毒婦竟也來了罢吃?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,176評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤昭齐,失蹤者是張志新(化名)和其女友劉穎尿招,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體阱驾,經(jīng)...
    沈念sama閱讀 45,619評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡就谜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了里覆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片丧荐。...
    茶點(diǎn)故事閱讀 39,932評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖喧枷,靈堂內(nèi)的尸體忽然破棺而出虹统,到底是詐尸還是另有隱情,我是刑警寧澤隧甚,帶...
    沈念sama閱讀 35,655評(píng)論 5 346
  • 正文 年R本政府宣布车荔,位于F島的核電站,受9級(jí)特大地震影響戚扳,放射性物質(zhì)發(fā)生泄漏忧便。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評(píng)論 3 329
  • 文/蒙蒙 一咖城、第九天 我趴在偏房一處隱蔽的房頂上張望茬腿。 院中可真熱鬧呼奢,春花似錦、人聲如沸切平。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽悴品。三九已至禀综,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間苔严,已是汗流浹背定枷。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留届氢,地道東北人欠窒。 一個(gè)月前我還...
    沈念sama閱讀 48,095評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像退子,于是被迫代替她去往敵國和親岖妄。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評(píng)論 2 354

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

  • 一:java概述:1寂祥,JDK:Java Development Kit荐虐,java的開發(fā)和運(yùn)行環(huán)境,java的開發(fā)工...
    ZaneInTheSun閱讀 2,650評(píng)論 0 11
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法丸凭,類相關(guān)的語法福扬,內(nèi)部類的語法,繼承相關(guān)的語法惜犀,異常的語法铛碑,線程的語...
    子非魚_t_閱讀 31,631評(píng)論 18 399
  • 前言 人生苦多,快來 Kotlin 向拆,快速學(xué)習(xí)Kotlin亚茬! 什么是Kotlin酪耳? Kotlin 是種靜態(tài)類型編程...
    任半生囂狂閱讀 26,209評(píng)論 9 118
  • 1.官方說明:點(diǎn)擊這里2.翻譯請(qǐng)看簡書:這里
    北京的天空閱讀 125評(píng)論 0 0
  • 南懷瑾先生講浓恳,為人的最高境界是儒為表,佛為心碗暗,道為骨颈将。今天吳老師講學(xué),亦不乏儒釋道融合并濟(jì)的思想言疗。今晚的芥子晴圾,也可...
    LAI賴皮閱讀 467評(píng)論 0 1