反射概念的引出
問題1:
1.對(duì)象有編譯類型和運(yùn)行類型<pre><code>Object obj = new Date();</pre></code>編譯類型:Object
運(yùn)行類型(其實(shí)就是obj對(duì)象真實(shí)的類型):Date
需求:根據(jù)對(duì)象obj調(diào)用Date類中的一個(gè)方法,toLocaleString(),如何來做?
obj.toLocaleString()代碼在編譯階段去編譯類型Object中檢查是否有該方法,若沒有,編譯失敗.
解決方案1:強(qiáng)制轉(zhuǎn)換obj為Date類型,前提:必須知道對(duì)象的真實(shí)類型是什么?
<pre><code>Date d = (Date)obj;
d.toLocaleString();//YES</pre></code>如果我們不知道obj的真實(shí)類型,那又如何去調(diào)用toLolcaeString()方法.如何去做?
問題2:
見下圖(好好理解下面這張圖):


eclipse-outline功能就是反射的一個(gè)很好的例子。
Class類與Class實(shí)例
Class 類的實(shí)例表示正在運(yùn)行的 Java 應(yīng)用程序中的類和接口。枚舉是一種類,注釋是一種接口。每個(gè)數(shù)組屬于被映射為 Class 對(duì)象的一個(gè)類,所有具有相同元素類型和維數(shù)的數(shù)組都共享該 Class 對(duì)象。基本的 Java 類型(boolean、byte、char、short、int、long、float和 double)和關(guān)鍵字 void 也表示為 Class 對(duì)象。
Class 沒有公共構(gòu)造方法。Class 對(duì)象是在加載類時(shí)由 Java 虛擬機(jī)以及通過調(diào)用類加載器中的 defineClass 方法自動(dòng)構(gòu)造的(摘自JDK文檔Class類說明)。
Class實(shí)例:就是指JVM中一份字節(jié)碼
Class類:用于描述一切類/接口.問題:那Class實(shí)例到底表示的是哪一份字節(jié)碼,為了明確區(qū)分出Class實(shí)例表示的是誰的字節(jié)碼.Class類提供了泛型
<pre><code>
Class<Date> clz1 = Date.class;//clz1表示是Date的字節(jié)碼
Class<String> clz2 = String.class;//clz2表示的是String的字節(jié)碼 </pre></code>
如何得到Class的實(shí)例:
1.類名.class(就是一份字節(jié)碼)(注:類名改成數(shù)據(jù)類型可能更合適,因?yàn)檫€有幾本數(shù)據(jù)類型和void關(guān)鍵字,他們不是類名)
2.Class.forName(String className);根據(jù)一個(gè)類的全限定名來構(gòu)建Class對(duì)象(這種方式用的最多)
3.每一個(gè)對(duì)象多有g(shù)etClass()方法:obj.getClass();返回對(duì)象的真實(shí)類型***
一個(gè)類在JVM中只有一份字節(jié)碼;
<pre><code>//第一種方式:數(shù)據(jù)類型.class
Class<Person>clz1 = Person.class;
//第二中方式:Class.forName(String className);
Class<?> clz2 =Class.forName("com.reflex.Person");
//第三種方式: 對(duì)象.getClass();得到對(duì)象的真實(shí)類型
Person u = new Person();
Class clz3 = u.getClass();
</pre></code>
clz1 == clz2 == clz3:因?yàn)楸硎径际荍VM中共同的一份字節(jié)碼(Person.class)
反射很強(qiáng)大,但是耗性能.主要是為了做工具和框架使用的.