一、引出反射機制
在引出反射機制之前我們先思考兩個問題:
問題一
我們知道對象有編譯類型
和運行類型
Object obj = new java.util.Date();
編譯類型:Object
運行類型:java.util.Date
需求: 通過obj對象蚁袭,調(diào)用java.util.Date類中的toLocaleString()方法栗恩;
package java.util.Date;
@Deprecated//意思是說此方法已過時护锤,過時的原因就是有新的API的類(Calender)替代了此方法关贵。
//這個被劃去的方法仍然是可以正常使用的诱告,就是一個提示而已扮匠。
//非static修飾悲柱,即用對象調(diào)用锋喜;
public String toLocaleString() {
DateFormat formatter = DateFormat.getDateTimeInstance();
return formatter.format(this);
}
如果我們直接使用:
obj.toLocalString();
//此時編譯報錯,編譯時會檢查該編譯類型中是否存在該方法诗祸。
//存在編譯成功跑芳,不存在編譯失敗直颅;
解決方案:
因為obj的真實類型是java.util.Date類博个,所以我們可以把obj對象強制轉(zhuǎn)換為java.util.Date類型;
java.util.Date date = (java.util.Date)obj ;
date.toLocalString();//調(diào)用成功
但是功偿,如果不知道obj的真實類型盆佣,就不能強轉(zhuǎn)(假設(shè)底層有一個方法,返回一個Object類型的java.util.Date對象)
例如:
public static Object getObj(){
return new java.util.Date();
}
此時問題如何解決械荷?
問題二
在面向?qū)ο笏枷胫泄菜#磺惺挛锒伎梢钥闯墒菍ο螅敲磫栴}來了:
-類這種事物是什么對象吨瞎?
-又使用什么類來描述類這種對象痹兜?
要解決上述兩個問題,就要用到反射機制,在學習了反射機制后這兩個問題也就迎刃而解了颤诀。我相信在解決了這兩個問題之后字旭,你會對反射有很清晰的認識对湃。
二、Class類和Class實例
在講反射之前遗淳,我們再來思考一個問題:
//有三個類拍柒,我們分別為它們創(chuàng)建三個對象:
Date d1 = new Date();
Date d2 = new Date();
Date d3= new Date();
String s1 = "A";
String s2 = "B";
String s3 = "C";
ArrayList l1 = new ArrayList();
ArrayList l2 = new ArrayList();
ArrayList l3 = new ArrayList();
在Java中,對于類和對象的關(guān)系屈暗,我們說類是用來描述對象
的拆讯,并且該類只能描述該類型的對象。
那么在這里养叛,d1种呐、d2、d3
是Date類型
的一铅;s1陕贮、s2、s3
是String類型
潘飘;l1、l2掉缺、l3
是ArrayList 類型
的卜录。
也就是說我們使用Date類來描述
它的三個對象,String類和ArrayList類也是同樣如此眶明;
在Java面向?qū)ο笏枷胫屑瓒荆磺惺挛锒伎梢钥醋魇菍ο螅敲磫栴}來了:
類這種事物是啥對象呢搜囱?
又或者說我們用什么來描述類這種事物呢丑瞧?
要描述對象,當然要用到類蜀肘。這個類就是java.lang.Class
绊汹。
這個類是用來描述字節(jié)碼對象
的。為什么說是用來描述字節(jié)碼對象
呢扮宠,在《Java的類加載機制》一章提過西乖,類一旦加載到內(nèi)存,就會變成Class對象(字節(jié)碼對象)坛增。
Class類:用來描述類或者接口的類型获雕,描述類的類。
Class實例:Class實例(JVM中的一份份字節(jié)碼)表示運行在JVM中的類或者接口收捣。
枚舉是一種特殊的類,注解是一種特殊的接口届案。
當程序第一次使用某一個java.util.Date類的時候,就會把該類的字節(jié)碼對象加載進JVM罢艾,并創(chuàng)建出一個Class對象楣颠;
此時的Class對象就表示java.util.Date的字節(jié)碼尽纽;
Class類可以表示N個類的字節(jié)碼對象 ,問題:到底怎么區(qū)分Class類此時表示的是哪一個類的字節(jié)碼呢球碉?
為了解決這個問題蜓斧,Class類設(shè)計者使用了泛型
,即:Class<T> 睁冬;
T - 由此Class對象建模的類的類型挎春;
例如String.class的類型是Class<String>;
如果將被建模的類未知豆拨,則使用Class<?>直奋;
三、什么是反射
補充一個元數(shù)據(jù)(metedata)的概念施禾。元數(shù)據(jù):描述數(shù)據(jù)的描述數(shù)據(jù)
脚线。
那么在上幅圖中,我們用類描述對象弥搞,使用java.lang.Class
描述類邮绿。所以java.lang.Class
就屬于元數(shù)據(jù)這種級別的。
有了前面的知識基礎(chǔ)攀例,我們就可以開始簡單的聊聊什么是反射了船逮。
反射:得到類的元數(shù)據(jù)的過程。
更細致的來說就是粤铭,在運行時期挖胃,動態(tài)地去獲取某一個類中的成員信息(構(gòu)造器、方法梆惯、字段酱鸭、內(nèi)部類、接口垛吗、父類等)凹髓。
四、反射的主要用途
其實我們經(jīng)常都在接觸反射职烧,比如當我們在使用IDE(如Eclipse扁誓,IDEA)時,當我們輸入一個對象或類并想調(diào)用它的屬性或方法時蚀之,一按“.”號蝗敢,編譯器就會自動列出它的屬性或方法,這里就會用到反射足删。
又或者我們經(jīng)常會看到這些IDE會有大綱(Outline)寿谴,通過大綱我們可以很清楚的看到一個Java類中的所有信息,如:包名失受、類名讶泰、構(gòu)造器咏瑟、方法、字段等等痪署,這些都是使用了反射機制來實現(xiàn)码泞;
?反射最重要的用途就是開發(fā)各種通用框架。