java筆記(一)java的反射機制

前言

java反射機制指的是在java運行過程中,對于任意的類都可以知道他的所有屬性以及方法钮热,對于任意一個對象都可以任意的調(diào)用他的屬性和方法犁功,這種動態(tài)獲取對象信息和動態(tài)調(diào)用對象方法的功能稱為java反射機制,但是反射使用不當(dāng)會造成很高的成本腰根。

簡單實例


反射獲取類名稱

package top.crosssoverjie.study;
public class Reflect {
    public static void main(String[] args) {
        Class<Reflect> c1 = Reflect.class;
        System.out.println(c1.getName());
        
        Reflect r1 = new Reflect() ;
        Class<Reflect> c2 = (Class<Reflect>) r1.getClass() ;
        System.out.println(c2.getName());
        
        try {
            Class<Reflect> c3 = (Class<Reflect>) Class.forName("top.crosssoverjie.study.Reflect");
            System.out.println(c3.getName());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

輸出結(jié)果:

top.crosssoverjie.study.Reflect
top.crosssoverjie.study.Reflect
top.crosssoverjie.study.Reflect  

以上的 c1,c2,c3是完全一樣的巢音,他們都有一個統(tǒng)一的名稱:叫做Reflect類的類類型。


反射的用處

獲取成員方法

public Method getDeclaredMethod(String name,Class<?>...parameterTypes)//得到該類的所有方法尽超,但是不包括父類的方法官撼。
public Method getMethod(String name,Class<?>...parameterTypes)//獲得該類的所有public方法,包括父類的似谁。

通過反射獲取成員方法調(diào)用的實例:

package top.crosssoverjie.study;

import java.lang.reflect.Method;

public class Person {
    private String name="crossover" ;
    private String msg ;
    
    public Person(String name, String msg) {
        this.name = name;
        this.msg = msg;
        System.out.println(name+"的描述是"+msg);
    }

    public Person() {
        super();
    }

    public void say(String name ,String msg){
        System.out.println(name+"說:"+msg);
    }
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
    
    public static void main(String[] args) {
        try {
            //首先獲取類類型
            Class c1 = Class.forName("top.crosssoverjie.study.Person") ;
            
            //通過newInstance()方法生成一個實例
            Object o1 = c1.newInstance() ;
            
            //獲取該類的say方法
            Method m1 = c1.getMethod("say", String.class,String.class) ;
            
            //通過invoke方法調(diào)用該方法
//            m1.invoke(o1, "張三","你好啊") ;
            
            Method[] methods = c1.getDeclaredMethods() ;
//            for(Method m : methods){
//                System.out.println(m.getName());
//            }
            
            Method[] methods2 = c1.getMethods() ;
            for (Method method : methods2) {
                System.out.println(method.getName());
            }
            
        } catch (Exception e) {
            e.printStackTrace();
        }
        
    }
}

輸出結(jié)果:

張三說:你好啊

所以我們只要知道類的全限定名就可以任意的調(diào)用里面的方法傲绣。


Method[] methods = c1.getDeclaredMethods() ;
for(Method m : methods){
    System.out.println(m.getName());
}

輸出結(jié)果:

main
getName
setName
say
getMsg
setMsg

使用的還是之前那個Person類掠哥,所以這里只寫了關(guān)鍵代碼。這里輸出的是Person的所有public方法秃诵。

如果我們調(diào)用getMethods()方法會是什么結(jié)果呢续搀?

Method[] methods2 = c1.getMethods() ;
for (Method method : methods2) {
    System.out.println(method.getName());
}

輸出結(jié)果:

main
getName
setName
say
getMsg
setMsg
wait
wait
wait
hashCode
getClass
equals
toString
notify
notifyAll

這時我們會發(fā)現(xiàn)這里輸出的結(jié)果會比剛才多得多,這時因為getMethods()方法返回的是包括父類的所有方法菠净。


獲取成員變量

我們還可以通過反射來獲取類包括父類的成員變量禁舷,主要方法如下:

public Field getDeclaredFiled(String name)//獲得該類所有的成員變量,但不包括父類的毅往。
public Filed getFiled(String name)//獲得該類的所有的public變量牵咙,包括其父類的。

還是按照之前例子中的Person類舉例攀唯,他具有兩個成員變量:

    private String name="crossover" ;
    private String msg ;

我們可以通過以下方法來獲取其中的成員變量:

Class c1 = Class.forName("top.crosssoverjie.study.Person") ;
Field field = c1.getDeclaredField("name");//獲取該類所有的成員屬性

通過以下例子可以獲取指定對象上此field的值:

package top.crosssoverjie.study;

import java.io.File;
import java.lang.reflect.Field;

public class Reflect {
    public static void main(String[] args) {
        try {
            Class c1 = Class.forName("top.crosssoverjie.study.Person");
            Field field = c1.getDeclaredField("name") ;
            Object o1 = c1.newInstance() ;
            /**
             * 由于Person類中的name變量是private修飾的洁桌,
             * 所以需要手動開啟允許訪問,是public修飾的就不需要設(shè)置了
             */
            field.setAccessible(true);
            Object name = field.get(o1) ;
            System.out.println(name);
        } catch (Exception e) {
            e.printStackTrace() ;
        }
//        Class<Reflect> c1 = Reflect.class;
//        System.out.println(c1.getName());
//        
//        Reflect r1 = new Reflect() ;
//        Class<Reflect> c2 = (Class<Reflect>) r1.getClass() ;
//        System.out.println(c2.getName());
//        
//        try {
//            Class<Reflect> c3 = (Class<Reflect>) Class.forName("top.crosssoverjie.study.Reflect");
//            System.out.println(c3.getName());
//        } catch (ClassNotFoundException e) {
//            e.printStackTrace();
//        }
    }
}

輸出結(jié)果:

crossover

我們也可以通過方法getDeclaredFieds()方法來獲取所有的成員變量侯嘀,返回是是一個Field[]數(shù)組另凌,只需要遍歷這個數(shù)組即可獲所有的成員變量。例子如下:

Field[] fields = c1.getDeclaredFields() ;
for(Field f :fields){
    System.out.println(f.getName());
}

輸出結(jié)果如下:

name
msg

獲取構(gòu)造方法

可以通過以下兩個方法來獲取構(gòu)造方法:

public Constructor getDeclaredConstructor(Class<?>...parameterTypes)//獲取該類的所有構(gòu)造方法戒幔,不包括父類的吠谢。
public Constructor getConstructor(Class<?>...parameterTypes)//獲取該類的所有public修飾的構(gòu)造方法,包括父類的溪食。

在之前的Person類中有以下的構(gòu)造方法:

    public Person(String name, String msg) {
        this.name = name;
        this.msg = msg;
    }

我們可以通過以下方法來獲取Person類的構(gòu)造方法:

Constructor dc1 = c1.getDeclaredConstructor(String.class,String.class) ;

具體代碼如下:

    Constructor dc1 = c1.getDeclaredConstructor(String.class,String.class) ;
    dc1.setAccessible(true);
    dc1.newInstance("小明","很帥") ;

dc1.newInstance("小明","很帥");方法調(diào)用了Person類中的:

    public Person(String name, String msg) {
        this.name = name;
        this.msg = msg;
        System.out.println(name+"的描述是"+msg);
    }

這個構(gòu)造方法囊卜,如果不傳參數(shù)的話,那么調(diào)用的就是無參的構(gòu)造方法错沃。輸出結(jié)果為:

小明的描述是很帥

通過反射了解集合泛型的本質(zhì)

通過以下例子程序可以看出:

package top.crosssoverjie.study;

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

public class GenericEssence {
    public static void main(String[] args) {
        //聲明兩個list栅组,一個有泛型,一個沒有泛型
        List list1 = new ArrayList() ;
        List<String> list2 = new ArrayList<String>() ;
        
        list2.add("你好") ;
//        list2.add(11) ;加上泛型之后在編譯期間只能添加String枢析,不然會報錯玉掸。
        System.out.println("list2的長度是:"+list2.size());
        
        
        Class c1 = list1.getClass();
        Class c2 = list2.getClass() ;
        System.out.print("c1,c2是否相等:");
        System.out.println(c1==c2);
        
        try {
            //通過反射繞過編譯器動態(tài)調(diào)用add方法,可能否加入非String類型的元素
            Method method = c2.getDeclaredMethod("add", Object.class) ;
            method.invoke(list2, 123) ;//在這里加入int類型醒叁,在上面如果加入int會出現(xiàn)編譯報錯司浪。
            
            //list2的長度增加了,說明添加成功了
            System.out.println("現(xiàn)在list2的長度是:"+list2.size());
            
            /**
             * 所以可以看出把沼,泛型只是在編譯期間起作用啊易,在經(jīng)過編譯進(jìn)入運行期間是不起作用的。
             * 就算是不是泛型要求的類型也是可以插入的饮睬。
             */
            
        } catch (Exception e) {
            e.printStackTrace() ;
        }
        
    }
}

所以可以看出租谈,泛型只是在編譯期間起作用,在經(jīng)過編譯進(jìn)入運行期間是不起作用的捆愁。就算是不是泛型要求的類型也是可以插入的割去。

反射知識點

泛型

總結(jié)

泛型的應(yīng)用比較多:

  • spring的IOC/DI窟却。
  • JDBC中的中的加載驅(qū)動

參考

個人博客地址:http://crossoverjie.top
GitHub地址:https://github.com/crossoverJie呻逆。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末夸赫,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子咖城,更是在濱河造成了極大的恐慌茬腿,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件酒繁,死亡現(xiàn)場離奇詭異滓彰,居然都是意外死亡,警方通過查閱死者的電腦和手機州袒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進(jìn)店門揭绑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人郎哭,你說我怎么就攤上這事他匪。” “怎么了夸研?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵邦蜜,是天一觀的道長。 經(jīng)常有香客問我亥至,道長悼沈,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任姐扮,我火速辦了婚禮絮供,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘茶敏。我一直安慰自己壤靶,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布惊搏。 她就那樣靜靜地躺著贮乳,像睡著了一般。 火紅的嫁衣襯著肌膚如雪恬惯。 梳的紋絲不亂的頭發(fā)上向拆,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天,我揣著相機與錄音酪耳,去河邊找鬼亲铡。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的奖蔓。 我是一名探鬼主播,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼讹堤,長吁一口氣:“原來是場噩夢啊……” “哼吆鹤!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起洲守,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤疑务,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后梗醇,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體知允,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年叙谨,在試婚紗的時候發(fā)現(xiàn)自己被綠了温鸽。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡手负,死狀恐怖涤垫,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情竟终,我是刑警寧澤蝠猬,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站统捶,受9級特大地震影響榆芦,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜喘鸟,卻給世界環(huán)境...
    茶點故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一匆绣、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧迷守,春花似錦犬绒、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至礼华,卻和暖如春咐鹤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背圣絮。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工祈惶, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓捧请,卻偏偏與公主長得像凡涩,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子疹蛉,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,086評論 2 355

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

  • 20- 枚舉,枚舉原始值,枚舉相關(guān)值,switch提取枚舉關(guān)聯(lián)值 Swift枚舉: Swift中的枚舉比OC中的枚...
    iOS_恒仔閱讀 2,282評論 1 6
  • 一:java概述:1活箕,JDK:Java Development Kit,java的開發(fā)和運行環(huán)境可款,java的開發(fā)工...
    ZaneInTheSun閱讀 2,654評論 0 11
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法育韩,類相關(guān)的語法,內(nèi)部類的語法闺鲸,繼承相關(guān)的語法筋讨,異常的語法,線程的語...
    子非魚_t_閱讀 31,644評論 18 399
  • (一)Java部分 1摸恍、列舉出JAVA中6個比較常用的包【天威誠信面試題】 【參考答案】 java.lang;ja...
    獨云閱讀 7,111評論 0 62
  • 手工課上的布娃娃我只把輪廓從布上剪下來悉罕,再縫了小兔子布娃娃的左耳朵,下星期四就要展覽了误墓,這個周末必須做完這...
    袁名緣閱讀 573評論 0 0