理解java中反射Class.forName,Class.forName().instance

先了解一下反射(這玩意著實讓我理解了很久啊)博文參考(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()調用類加載器

理解java中反射Class.forName,Class.forName().instance

理解java中反射Class.forName,Class.forName().instance

可以看到static塊其實是在初始化後執行的

如果調用Class.forName("A",false,this.getClass().getClassLoader());

就會發現只加載不初始化static塊沒有執行,什麼沒有輸出,所以網上很多說靜態塊代碼在類加載時執行不準確的,其實還是在初始化後執行

理解java中反射Class.forName,Class.forName().instance

需要補充的是:Class.forName("完整類名").newInstance();的用法相當於直接new();

3.Class c=類名.class

---------------------------------------------------------------------------------

Class.forName()加載一個類,返回的該類的類名

newInstance()方法可以創建一個Class對象的實例,使用該方法實例化一個類時該類必須已經被加載了

new關鍵字實例化一個類時先加載再實例化

獲取類名:(請無視我的包名啊,懶得改了啊啊啊)

理解java中反射Class.forName,Class.forName().instance

理解java中反射Class.forName,Class.forName().instance

三種方法都可以獲取。這裡要注意的是A中的構造方法值執行了一次,說明類A只加載了一次。

也就是說程序在運行時JVM先檢查類是否已加載,如果已加載就不在加載第二次。

Class類應用:

這裡介紹一個Constructor類,該類的對象可以通過Class中getConstructor獲得,用於獲取構造方法創建對象

上面的類A不變,修改Test類如下:

理解java中反射Class.forName,Class.forName().instance

理解java中反射Class.forName,Class.forName().instance

可以看到獲取到了類A中有參的構造方法

獲取類的結構:

理解java中反射Class.forName,Class.forName().instance

這裡需要主要的是隻執行了靜態初始化塊中的內容,應為只加載了類但是沒有實例化,static塊是跟隨類加載時執行的。

獲取類的全部方法:

這裡我在類A里加了個AA()方法

理解java中反射Class.forName,Class.forName().instance

Test類

理解java中反射Class.forName,Class.forName().instance

可以看到AA()方法和一些其他ang裡面的方法(報錯的線程錯誤無視掉好了)

取得類中的全部屬性:用到Field類

getDeclaredFielsd()方法可以獲取全部屬性,getFields()只能獲取公共屬性

我先在類A中加入一些簡單的屬性

理解java中反射Class.forName,Class.forName().instance

Test類

理解java中反射Class.forName,Class.forName().instance

看到類A中的屬性都打印出來了。

OK了,類似的還可以獲取屬性的值,類的父類和實現的接口·····當需要時查一下API就可以了,比較簡單,這裡就不一一列舉了


分享到:


相關文章: