先了解一下反射(這玩意著實讓我理解了很久啊)博文參考(http://blog.csdn.net/cookieweb/article/details/7056277)
先了解一些基本的概念:運行時,編譯時,編譯型,解釋型,類加載器,動態加載類
什麼是編譯?將原程序翻譯成計算機語言,就是二進制代碼,在java中是將.java文件也就是源程序翻譯成.class的字節碼
什麼是編譯時?將原程序翻譯成計算機語言的過程中,將.java翻譯為.class文件的過程
什麼是運行時?就是在啟動這個程序的時候,在java中是,類加載器加載.class文件,並交給jvm處理
什麼是編譯型語言?將原程序一次性全部轉換為二進制代碼,然後執行程序
什麼是解釋型語言?轉換一句,執行一句,java是既編譯又解釋的語言
編譯型語言和解釋型語言的區別:編譯型語言效率高,依賴於編譯器,但是跨平臺差,解釋型的效率低,依賴於解釋器,但跨平臺強
什麼是類加載器?類加載器就是JVM中的類裝載器,作用就是將編譯好的.class字節碼運到檢查器進行安全檢查的,檢查通過後開始解釋執行
什麼是運行時動態加載類?
反射就是可以將一個程序(類)在運行的時候獲得該程序(類)的信息的機制,也就是獲得在編譯期不可能獲得的類的信息,因為這些信息是保存在Class對象中的,而這個Class對象是在程序運行時動態加載的
它 就是可以在程序運行的時候動態裝載類,查看類的信息,生成對象,或操作生成對象。類在運行的時候,可以得到該類的信息,並且 可以動態的修改這些信息。class對象是在運行的時候產生的,通過class對象操作類的信息是在運行時進行的,當運行 程序的時候,類加載器會加載真正需要的類,什麼是真正需要的呢?就是該類真正起作用,如:有該類的對象實例,或該類調用了靜態方法屬性等
那麼如何實現反射呢
得到Class對象
Class類
要正確使用Java反射機制就得使用java.lang.Class這個類。它是Java反射機制的起源。當一個類被加載以後,Java虛擬機就會自動產 生一個Class對象。通過這個Class對象我們就能獲得加載到虛擬機當中這個Class對象對應的方法、成員以及構造方法的聲明和定義等信息。 三種方式得到Class對象:
1.調用對象的getClass方法,返回該對象的Class對象
2.Class.forName(“類的完整名字”);有個受查異常 //重要,可以在類不確定的情況下實例化Class,最靈活
這個方法內部默認調用Class.forName("A",true,this.getClass().getClassLoader());
true:是否實例化該類,也就是說實際上調用Class.forName(“類的完整名字”)加載類時執行初始化
this.getClass().getClassLoader()調用類加載器
可以看到static塊其實是在初始化後執行的
如果調用Class.forName("A",false,this.getClass().getClassLoader());
就會發現只加載不初始化static塊沒有執行,什麼沒有輸出,所以網上很多說靜態塊代碼在類加載時執行不準確的,其實還是在初始化後執行
需要補充的是:Class.forName("完整類名").newInstance();的用法相當於直接new();
3.Class c=類名.class
---------------------------------------------------------------------------------
Class.forName()加載一個類,返回的該類的類名
newInstance()方法可以創建一個Class對象的實例,使用該方法實例化一個類時該類必須已經被加載了
new關鍵字實例化一個類時先加載再實例化
獲取類名:(請無視我的包名啊,懶得改了啊啊啊)
三種方法都可以獲取。這裡要注意的是A中的構造方法值執行了一次,說明類A只加載了一次。
也就是說程序在運行時JVM先檢查類是否已加載,如果已加載就不在加載第二次。
Class類應用:
這裡介紹一個Constructor類,該類的對象可以通過Class中getConstructor獲得,用於獲取構造方法創建對象
上面的類A不變,修改Test類如下:
可以看到獲取到了類A中有參的構造方法
獲取類的結構:
這裡需要主要的是隻執行了靜態初始化塊中的內容,應為只加載了類但是沒有實例化,static塊是跟隨類加載時執行的。
獲取類的全部方法:
這裡我在類A里加了個AA()方法
Test類
可以看到AA()方法和一些其他ang裡面的方法(報錯的線程錯誤無視掉好了)
取得類中的全部屬性:用到Field類
getDeclaredFielsd()方法可以獲取全部屬性,getFields()只能獲取公共屬性
我先在類A中加入一些簡單的屬性
Test類
看到類A中的屬性都打印出來了。
OK了,類似的還可以獲取屬性的值,類的父類和實現的接口·····當需要時查一下API就可以了,比較簡單,這裡就不一一列舉了
閱讀更多 java執行官 的文章