日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

java高级反射_反射---Java高级开发必须懂的

發(fā)布時間:2024/9/27 java 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java高级反射_反射---Java高级开发必须懂的 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

理解反射對學(xué)習(xí)Java框架有很大的幫助,如Spring框架的核心就是使用Java反射實現(xiàn)的,而且對做一些Java底層的操作會很有幫助。

一、Class類的使用

1、萬事萬物皆對象,(當(dāng)然,基本數(shù)據(jù)類型,靜態(tài)成員不是面向?qū)ο?屬于類的)),所以我們創(chuàng)建的每一個類也都是對象,即類本身是java.lang.Class類的實例對象,但是這些對象都不需要new出來,因為java.lang.Class類的構(gòu)造方法是私有的

2、任何一個類都是Class類的實例對象,這個實例對象有三種表示方式:(我們新建一個Student類)

① Class c1 = Student.class;//實際告訴我們?nèi)魏我粋€類都有一個隱含的靜態(tài)成員變量class(知道類名時用)

② Class c2 = stu.getClass();//已知該類的對象通過getClass方法(知道對象時用)

③Class c3 = Class.forName("類的全名");//會有一個ClassNotFoundException異常

官網(wǎng)解釋說:c1,c2表示了Student類的類類型()class type),萬事萬物皆對象,類也是對象,是Class類的實例對象,這個對象我們成為該類的類類型(有點亂,但是慢慢捋一下還是能理解的)

這里有一點值得注意,當(dāng)我們執(zhí)行System.out.println(c1==c2);語句,結(jié)果返回的是true,這是為什么呢?原因是不管c1還是c2都代表了Student類的類類型,一個類可能是Class類的一個實例對象。

我們完全可以通過類的類類型創(chuàng)建該類的對象實例,即通過c1或c2創(chuàng)建Student的實例。

Student stu = (Student)c1.newInstance();//前提是必須要有無參的構(gòu)造方法,因為該語句會去調(diào)用其無參構(gòu)造方法。該語句會拋出異常。

二、動態(tài)加載類

1、編譯時加載類是靜態(tài)加載類,

new 創(chuàng)建對象是靜態(tài)加載類,在編譯時刻就需要加載所有可用使用到的類,如果有一個用不了,那么整個文件都無法通過編譯

2、運行時加載類是動態(tài)加載類

Class c = ?Class.forName("類的全名"),不僅表示了類的類型,還表示了動態(tài)加載類,編譯不會報錯,在運行時才會加載,使用接口標(biāo)準(zhǔn)能更方便動態(tài)加載類的實現(xiàn)。功能性的類盡量使用動態(tài)加載,而不用靜態(tài)加載。

很多軟件比如QQ,360的在線升級,并不需要重新編譯文件,只是動態(tài)的加載新的東西

三、獲取方法信息

1、基本的數(shù)據(jù)類型,void關(guān)鍵字都存在類類型

1 Class c1 =int.class;//int的類類型

2 Class c2 =String.class;//String類的類類型,可以理解為編譯生成的那個String.class字節(jié)碼文件,3 //當(dāng)然,這并不是官方的說法

4 Class c3 =double.class;5 Class c4 =Double.class;6 Class c5 =void.class;

2、Class類的基本API操作

1 /**

2 * 打印類的信息,包括類的成員函數(shù),成員變量3 *@paramobj 該對象所屬類的信息4 */

5 publicstaticvoid printClassMessage(Object obj){6 //要獲取類的信息,首先要獲取類的類類型

7 Class c = obj.getClass();//傳遞的是哪個子類的對象,c就是該子類的類類型8 //獲取類的名稱

9 System.out.println("累的名稱是:"+c.getName());10

11 /*

12 * Method類,方法的對象13 * 一個成員方法就是一個Method對象14 * getMethods()方法獲取的是所有的public的函數(shù),包括父類繼承而來的15 * getDeclaredMethods()獲取的是多有該類自己聲明的方法,不問訪問權(quán)限16 */

17 Method[] ms = c.getMethods();//c.getDeclaredMethods();

18 for(int i =0; i < ms.length; i++){19 //得到方法的返回值類型的類類型

20 Class retrunType =ms[i].getReturnType();21 System.out.print(retrunType.getName()+" ");22 //得到方法的名稱

23 System.out.print(ms[i].getName()+"(");24 //獲取的參數(shù)類型--->得到的是參數(shù)列表的類型的類類型

25 Class[] paraTypes =ms[i].getParameterTypes();26 for(Class class1 : paraTypes){27 System.out.print(class1.getName()+",");28 }29 System.out.println(")");30 }31 }

Class的API中還有很多其他的方法,可以得到interface、Package、Annotation等很多信息,具體使用請參考幫助手冊,本文就不在詳細講解。特別注意的一點是,如果你想得到一個類的信息,首先就要獲取該類的類類型。

四、獲取成員變量構(gòu)造函數(shù)信息

1 /**

2 * 成員變量也是對象,是java.lang.reflect.Field這個類的的對象3 * Field類封裝了關(guān)于成員變量的操作4 * getFields()方法獲取的是所有public的成員變量的信息5 * getDeclareFields()方法獲取的是該類自己聲明的成員變量的信息6 */

7 Field[] fs =c.getDeclaredFields();8 for(Field field : fs){9 //得到成員變量的類型的類類型

10 Class fieldType =field.getType();11 String typeName =fieldType.getName();12 //得到成員變量的名稱

13 String fieldName =field.getName();14 System.out.print(typeName+" "+fieldName);15 }16

17

18 /**

19 * 構(gòu)造函數(shù)也是對象20 * java.lang.Constructor中封裝了構(gòu)造函數(shù)的信息21 * getConstructor()方法獲取所有的public的構(gòu)造函數(shù)22 * getDeclaredConstructors得到所有的構(gòu)造函數(shù)23 */

24 Constructor[] cs =c.getDeclaredConstructors();25 for(Constructor constructor : cs){26 System.out.print(constructor.getName()+"(");27 //獲取構(gòu)造函數(shù)的參數(shù)列表---》得到的是參數(shù)雷彪的類類型

28 Class[] paramTypes =constructor.getParameterTypes();29 for(Class class1 : paramTypes){30 System.out.print(class1.getName()+",");31 }32 System.out.println(")");33 }

五、方法反射的基本操作

1、如何獲取某個方法

方法的名稱和方法的參數(shù)列表才能唯一決定某個方法

Method m = c.getDeclaredMethod("方法名",可變參數(shù)列表(參數(shù)類型.class))

2、方法的反射操作

m.invoke(對象,參數(shù)列表)

方法如果沒有返回值,返回null,如果有返回值返回Object類型,然后再強制類型轉(zhuǎn)換為原函數(shù)的返回值類型

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

1 ArrayList list1 =newArrayList();2 ArrayList list2 =newArrayList();3

4 Class c1 =list1.getClass();5 Class c2 =list2.getClass();6

7 System.out.println(c1==c2);//結(jié)果為true,為什么??

結(jié)果分析:因為反射的操作都是編譯之后的操作,也就是運行時的操作,c1==c2返回true,說明編譯之后集合的泛型是去泛型化的。

那么我們就可以理解為,Java集合中的泛型,是用于防止錯誤類型元素輸入的,比如在list2中我們add一個int,add(10)就會編譯報錯,那么這個泛型就可以只在編譯階段有效,通過了編譯階段,泛型就不存在了??梢则炞C,我們繞過編譯,用反射動態(tài)的在list2中add一個int是可以成功的,只是這時因為list2中存儲了多個不同類型的數(shù)據(jù)(String型,和int型),就不能用for-each來遍歷了,會拋出類型轉(zhuǎn)換錯誤異常ClassCastException

=======================華麗的分隔線======================================

補充資料:

七、關(guān)于Java類加載器內(nèi)容的詳解

1、類的加載

當(dāng)程序要使用某個類時,如果該類還未被加載到內(nèi)存中,則系統(tǒng)會通過加載,連接,初始化三步來實現(xiàn)對這個類進行初始化

·加載:

就是指將class文件讀入內(nèi)存,并為之創(chuàng)建一個Class對象,任何類被使用時系統(tǒng)都會建立一個Class對象

·連接:

驗證:確保被加載類的正確性

準(zhǔn)備:負責(zé)為類的靜態(tài)成員分配內(nèi)存,并設(shè)置默認初始化值

解析:將類中的符號引用替換為直接引用

·初始化:

局部變量保存在棧區(qū):必須手動初始化

new 的對象保存在堆區(qū):虛擬機會進行默認初始化,基本數(shù)據(jù)類型初始化值為0,引用類型初始化值為null

2、類加載的時機(只加載一次)

以下時機僅表示第一次的時候

① 創(chuàng)建類的實例的時候

② 訪問類的靜態(tài)變量的時候

③ 調(diào)用類的靜態(tài)方法的時候

④ 使用反射方式來強制創(chuàng)建某個類或接口對應(yīng)的java.lang.Class對象

⑤ 初始化某個類的子類的時候

⑥ 直接使用java.exe命令來運行某個主類

3、類加載器

負責(zé)將.class文件加載到內(nèi)存中,并為之生成對應(yīng)的Class對象

雖然我們在開發(fā)過程中不需要關(guān)心類加載機制,但是了解這個機制我們就能更好的理解程序的運行

4、類加載器的組成:

①Bootstrap ClassLoader 根類加載器

也被稱為引導(dǎo)類加載器,負責(zé)Java核心類的加載,比如System類,在JDK中JRE的lib目錄下rt.jar文件中的類

②Extension ClassLoader 擴展類加載器

負責(zé)JRE的擴展目錄中jar包的加載,在JDK中JRE的lib目錄下ext目錄

③System ClassLoader 系統(tǒng)類加載器

負責(zé)在JVM啟動時加載來自java命令的class文件,以及classpath環(huán)境變量所指定的jar包和類路徑,主要是我們開發(fā)者自己寫的類

更多內(nèi)容請參考《深入理解JVM虛擬機》

總結(jié)

以上是生活随笔為你收集整理的java高级反射_反射---Java高级开发必须懂的的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。