JAVA 基礎(chǔ) 之 反射

一:Class類的使用


1: Class 類介紹

? ? 在Java中除了基本數(shù)據(jù)類型和靜態(tài)的東西都是對象,都是Java.lang.class的對象,

? ? 在上面的Code我們創(chuàng)建了一個Food類,實例化了一個food的對象, 其實Food這個類也是一個對象,是Java.lang.class的對象 。我們知道,通過new A(A任意一個類)來得到一個A類的對象,同樣任意一個類都是class的對象,我們也可以獲取到Class的對象

? ? 獲方式如下:

? ? ? ? ? 1:Class c1 = Food.class()

? ? ? ? ? 2:? Class c2 = food.getClass();

? ? ? ? ? ? 3: Classc3 = Class.forName(“com.xxx.xx”);

2:動態(tài)加載類

? ? ? 程序都分為編譯期和運行期2個時期。

? ? ? 編譯期:是指編譯器將源代碼翻譯為機器能識別的代碼,java為編譯為jvm認識的字節(jié)碼文件。?

? ? ? 運行期:則是指java代碼的運行過程。

? ? ? ? 在我們的FactoryFood中,我們需要根據(jù)實際情況引很多個類,而且我們需要編譯期編譯很多類,但實際可能只會用到1,2個類。

? ? ? 在我們的DynamicFactory中,我們沒有引入任何實體類,而是由程序動態(tài)的加載和創(chuàng)建對象。需要什么類就傳入什么類的包.類名即可

總結(jié):通過動態(tài)加載類的方式,我們可以隨意的添加和刪除類而不需要重新編譯。然而靜態(tài)類卻不行,每次新增類都需要重新編譯程序。

二:獲取方法信息


? ? 下面讓我們通過反射的方式來獲取類的名稱,方法,變量,函數(shù)的參數(shù),返回值

? ? getMethods():獲取所有的public方法,包括從父類繼承過來的,如上面的wait方法(在java中我們新建的類默認繼承Object,所以Food類里面就獲取到了warit方法)

? ? getDeclareMethods():獲取類自己申明的方法包括(public, private, protect)通過上面的輸出我們可以看出來,使用getDeclareMethods獲取到了updateFood(private)但是沒有獲取到wait(從父類繼承的)

三:獲取成員變量


? ? 前面我們介紹了方法的獲取方法,那成員變量依然可以獲取,而且成員變量也是對象是Java.lang.Field的對象,

? ? 我們先在類中添加一個public Character character的成員變量

? ? 下面演示獲取成員變量信息的例子

? ? getFields()只能獲取public的成員變量,在輸出信息中,我們可以看到只輸出了一個character的成員變量

? ? getDeclareField()可以獲取該類所有自己聲明的成員變量包括public的,private的和protected,以及default類型的

四:獲取構(gòu)造函數(shù)信息


? ? 類是對象,成員變量是對象,同樣構(gòu)造函數(shù)也是對象,是Java.lang.Constructor的對象。

? ? 下面讓我們來獲取構(gòu)造函數(shù)的參數(shù)列表和參數(shù)類型

? ? getConstructors():獲取所有的public的構(gòu)造函數(shù)(也有private的構(gòu)造函數(shù),比如:單例模式中就存在)

? ? getDeclareConstructors():獲取所有自己申明的構(gòu)造函數(shù)(構(gòu)造函數(shù)只能是自己申明的)

? ? 同樣我們也可以通過getInterface, getSuperClass獲取接口和父類

? ? 注:只要我們得到類的類型,我們就可以得到該類的所有信息

五:方法的反射


? ? 前面講述了一大堆獲取方法,變量,參數(shù),返回值的操作,接下來就來實際操作通過反射來調(diào)用我們的方法,指令method.invoke();

? ? 首先,我們要調(diào)用方法就要先獲取方法信息,要獲取方法信息就要獲取類信息,就是獲取類類型

? ? 首先我們在Food類中添加如下三個方法:

? ? 然后我們來反射調(diào)用這三個方法:

? ? 在上面的code中,我們先調(diào)用setDefaultName來給Food命名,然后在調(diào)用getFoodName來檢查我們是否成功的通過反射完成了設(shè)值,然后我們再調(diào)用有參數(shù)的方法setFoodNumber,來重新設(shè)置name和 number然后再調(diào)用getFoodName來檢查我們是否成功的通過反射完成了設(shè)值

? ? 從輸出的信息,我么可以得知我們成功的通過反射來完成了Food方法的調(diào)用,但是我們發(fā)現(xiàn),第一次的輸出是null,因為我們的第一次調(diào)用的函數(shù)是無返回值的。

? ? 注:當(dāng)有返回值,Object為具體的返回值,無返回值時,Object為null函數(shù)有參數(shù)時,調(diào)用時傳入具體的參數(shù),多個參數(shù),傳入一個Object數(shù)組;無參數(shù)調(diào)用時不傳參數(shù)

深入理解:

? ? 反射是編譯之后的操作,前面的文章我們講泛型,說泛型是編譯期的安全檢查,那我們就可以通過反射來給泛型插入數(shù)據(jù)而不出現(xiàn)編譯錯誤:

? ? 通過上面的輸出結(jié)果我們可以發(fā)現(xiàn)我們定義了String的ArrayList,添加了一個”First”,這時候size是1,然后又通過反射來添加一個22到ArrayList中,輸出的 Size是2。所以通過反射可以繞過泛型的檢查(因為編譯器在編譯期會做泛型擦除)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 課程地址:Java基礎(chǔ)之 — 反射(非常重要) (使用的前提條件:必須先得到代表的字節(jié)碼的Class,Cla...
    叨唧唧的閱讀 766評論 0 2
  • (轉(zhuǎn)自csdn) 反射是框架設(shè)計的靈魂 (使用的前提條件:必須先得到代表的字節(jié)碼的Class,Class類用于表示...
    尼爾君閱讀 284評論 0 1
  • Java-Reflect Class類的使用 方法的反射 成員變量的反射 構(gòu)造函數(shù)的反射 Java類加載機制 一、...
    廚房有只偷吃的貓閱讀 814評論 0 0
  • 一、兩個概念 編譯型語言:程序在執(zhí)行之前需要將源代碼編譯成機器語言,再由機器運行機器碼(二進制)。像C/C++、D...
    M_JCs閱讀 393評論 0 0
  • 1)類的加載 當(dāng)程序要使用某個類時,如果該類還未被加載到內(nèi)存中,則系統(tǒng)會通過加載,連接,初始化三步來實現(xiàn)對這個類進...
    糖寶_閱讀 239評論 0 2

友情鏈接更多精彩內(nèi)容