Java反射詳細介紹

反射

目錄介紹

1.反射概述java

1.1 反射概述程序員

1.2 獲取class文件對象的三種方式模塊化

1.3 反射經常使用的方法介紹性能

1.4 反射的定義spa

1.5 反射的組成插件

1.6 反射的做用有哪些對象

2.反射的相關使用繼承

2.1.1 經過反射獲取無參構造方法並使用接口

2.1.2 經過反射獲取帶參構造方法並使用ip

2.1.3 經過反射獲取私有構造方法並使用

2.1.4 經過反射獲取成員變量並使用

2.1.5 經過反射獲取無參無返回值成員方法並使用

2.1.6 經過反射獲取帶參無返回值成員方法並使用

2.1.7 經過反射獲取帶參帶返回值成員方法並使用

2.1.8 經過反射獲取無參帶返回值成員方法並使用

3.相關知識點

3.1.1 設置setAccessible(true)暴力訪問權限

3.1.2 獲取Filed兩個方法的區別

3.1.3 獲取Field的類型

3.1.4 Method獲取方法名,獲取方法參數

3.1.5 Method方法的invoke()方法執行

關於連接

1.技術博客彙總

2.開源項目彙總

3.生活博客彙總

4.喜馬拉雅音頻彙總

5.程序員聊天筆記彙總

5.其餘彙總

0.問題答疑

0.1 被反射的類是否必定須要無參構造方法?爲何?

0.2 反射的使用有什麼優點和劣勢?爲何說反射能夠下降耦合?

0.3 反射比較損耗性能,爲何這樣說?可否經過案例對比說明反射機制損耗性能……

0.4 反射是一種具備與類進行動態交互能力的一種機制,爲何要強調動態交互呢?

0.5 Java反射中的setAccessible()方法是否破壞了類的訪問規則

0.2 反射的使用有什麼優點和劣勢?

射的初衷不是方便你去建立一個對象,而是讓你在寫代碼的時候能夠更加靈活,下降耦合,提升代碼的自適應能力。

0.4 反射是一種具備與類進行動態交互能力的一種機制,爲何要強調動態交互呢

動態加載,也就是在運行的時候纔會加載,而不是在編譯的時候,在須要的時候才進行加載獲取,或者說你能夠在任什麼時候候加載一個不存在的類到內存中,而後進行各類交互,或者獲取一個沒有公開的類的全部信息,換句話說,開發者能夠隨時隨意的利用反射的這種機制動態進行一些特殊的事情。

1.反射概述

1.1 反射概述

JAVA反射機制是在運行狀態中,對於任意一個類,都可以知道這個類的全部屬性和方法;

對於任意一個對象,都可以調用它的任意一個方法和屬性;

這種動態獲取的信息以及動態調用對象的方法的功能稱爲java語言的反射機制。

要想解剖一個類,必須先要獲取到該類的字節碼文件對象。

而解剖使用的就是Class類中的方法,因此先要獲取到每個字節碼文件對應的Class類型的對象

1.2 獲取class文件對象的三種方式

1.2.1 這三種方式爲:

a:Object類的getClass()方法

b:靜態屬性class

c:Class類中靜態方法forName()

1.2.2 第一種方法【Object類的getClass()方法】

1.在內存中新建一個Person的實例,對象p對這個內存地址進行引用

2.對象p調用getClass()返回對象p所對應的Class對

3.調用newInstance()方法讓Class對象在內存中建立對應的實例,而且讓p2引用實例的內存地址

clipboard.png

1.2.3 第二種方法【靜態屬性class】

1.獲取指定類型的Class對象,這裏是Person

2.調用newInstance()方法在讓Class對象在內存中建立對應的實例,而且讓p引用實例的內存地址

clipboard.png

1.2.4 第三種方法【Class類中靜態方法forName()】

1.經過JVM查找並加載指定的類(上面的代碼指定加載了com.fanshe包中的Person類)

2.調用newInstance()方法讓加載完的類在內存中建立對應的實例,並把實例賦值給p

注意:若是找不到時,它會拋出 ClassNotFoundException 這個異常,這個很好理解,由於若是查找的類沒有在 JVM 中加載的話,天然要告訴開發者。

clipboard.png

1.3 經過反射獲取無參構造方法並使用

A:獲取全部構造方法

public Constructor[] getConstructors()

public Constructor[] getDeclaredConstructors()

B:獲取單個構造方法

public Constructor getConstructor(Class... parameterTypes)

public Constructor getDeclaredConstructor(Class... parameterTypes)

方法關鍵字

getDeclareMethods() 獲取全部的方法

getReturnType() 獲取方法的返回值類型

getParameterTypes() 獲取方法的傳入參數類型

getDeclareMethod("方法名,參數類型.class,....") 得到特定的方法

構造方法關鍵字

getDeclaredConstructors() 獲取全部的構造方法

getDeclaredConstructors(參數類型.class,....) 獲取特定的構造方法

成員變量

getDeclaredFields 獲取全部成員變量

getDeclaredField(參數類型.class,....) 獲取特定的成員變量

父類和父接口

getSuperclass() 獲取某類的父類

getInterfaces() 獲取某類實現的接口

1.4 反射的定義

JAVA反射機制是在運行狀態中,對於任意一個類,都可以知道這個類的全部屬性和方法;對於任意一個對象,都可以調用它的任意方法和屬性;這種動態獲取信息以及動態調用對象方法的功能稱爲java語言的反射機制

1.5 反射的組成

因爲反射最終也必須有類參與,所以反射的組成通常有下面幾個方面組成:

1.java.lang.Class.java:類對象;

2.java.lang.reflect.Constructor.java:類的構造器對象;

3.java.lang.reflect.Method.java:類的方法對象;

4.java.lang.reflect.Field.java:類的屬性對象;

反射中類的加載過程

根據虛擬機的工做原理,通常狀況下,類須要通過:加載->驗證->準備->解析->初始化->使用->卸載這個過程,若是須要反射的類沒有在內存中,那麼首先會通過加載這個過程,並在在內存中生成一個class對象,有了這個class對象的引用,就能夠發揮開發者的想象力,作本身想作的事情了。

1.6 反射的做用有哪些

前面只是說了反射是一種具備與Java類進行動態交互能力的一種機制,在Java和Android開發中,通常狀況下下面幾種場景會用到反射機制.

須要訪問隱藏屬性或者調用方法改變程序原來的邏輯,這個在開發中很常見的,因爲一些緣由,系統並無開放一些接口出來,這個時候利用反射是一個有效的解決方法

自定義註解,註解就是在運行時利用反射機制來獲取的。

在開發中動態加載類,好比在Android中的動態加載解決65k問題等等,模塊化和插件化都離不開反射,離開了反射步履維艱。

2.反射的相關使用

2.1.4 經過反射獲取成員變量[包含私有]並使用

clipboard.png

2.1.5 經過反射獲取無參無返回值成員方法[包含私有]並使用

clipboard.png

2.1.6 經過反射獲取帶參無返回值成員方法並使用

clipboard.png

2.1.7 經過反射獲取帶參帶返回值成員方法並使用

clipboard.png

3.相關知識點

3.1.1 設置.setAccessible(true)暴力訪問權限

通常狀況下,咱們並不能對類的私有字段進行操做,利用反射也不例外,但有的時候,例如要序列化的時候,咱們又必須有能力去處理這些字段,這時候,咱們就須要調用AccessibleObject上的setAccessible()方法來容許這種訪問,而因爲反射類中的Field,Method和Constructor繼承自AccessibleObject,所以,經過在這些類上調用setAccessible()方法,咱們能夠實現對這些字段的操做。

clipboard.png

3.1.2 獲取Filed兩個方法的區別

二者的區別就是 getDeclaredField() 獲取的是 Class 中被 private 修飾的屬性。 getField() 方法獲取的是非私有屬性,而且 getField() 在當前 Class 獲取不到時會向祖先類獲取。

clipboard.png

3.1.3 獲取Field的類型

能夠看到 getGenericType() 確實把泛型都打印出來了,它比 getType() 返回的內容更詳細。

clipboard.png

3.1.4 Method獲取方法名,獲取方法參數

clipboard.png

3.1.5 Method方法的invoke()方法執行

Method 調用 invoke() 的時候,存在許多細節:

invoke() 方法中第一個參數 Object 實質上是 Method 所依附的 Class 對應的類的實例,若是這個方法是一個靜態方法,那麼 ojb 爲 null,後面的可變參數 Object 對應的天然就是參數。

invoke() 返回的對象是 Object,因此實際上執行的時候要進行強制轉換。

在對Method調用invoke()的時候,若是方法自己會拋出異常,那麼這個異常就會通過包裝,由Method統一拋InvocationTargetException。而經過InvocationTargetException.getCause() 能夠獲取真正的異常。

本文做者:瀟湘劍雨

閱讀原文

本文爲雲棲社區原創內容,未經容許不得轉載。

相關文章
相關標籤/搜索