JAVA反射的概念
百度百科對Java反射的定義:JAVA反射機制是在運行狀態中,對于任意一個實體類,都能夠知道這個類的所有屬性和方法;對于任意一個對象,都能夠調用它的任意方法和屬性;這種動態獲取信息以及動態調用對象方法的功能稱為java語言的反射機制。
舉一個我使用到反射的例子:有一個類,它內部用一個private方法獲取到了原始信息,然后在對外public方法中將數據過濾返回。我現在想拿到原始數據,通過普通途徑是拿不到的,這時候就可以通過反射實現。
Java反射涉及到4個類和一個接口。四個類是Class類、Field類、Method類、Constructor類(后面三個類都屬于Java 反射類庫java.lang.reflect),一個接口是Member接口。
- Class類:實現反射功能是通過下面三個類和一個接口的。那么為什么需要Class類呢?第一,JVM創建對象之前必須加載該類的Class對象。第二,看源碼可以發現,下面三個類是沒有public構造器的,也就是說下面三個類的對象只能通過Class類來獲取。
- Constructor類:實現了Member接口。該類針對構造器。主要提供創建對象的功能。
- Field類:實現了Member接口。該類針對屬性。該類提供了獲取屬性的類型、修飾符、注解、變量名、值以及修改屬性值的功能(包括private屬性)
- Method類:實現了Member接口。該類針對方法。該類提供了獲取方法返回類型、方法參數類型、方法參數名稱、方法拋出異常類型、方法修飾符,以及通過反射調用方法等功能。
- Member接口:該類提供了一個方法AccessibleObject。所以實現類的對象都可以使用該方法取消 Java 語言訪問權限檢查。
一般使用反射,代碼步驟就是:
- 獲取目標類的Class對象
- 通過Class對象獲取Field對象或者Method對象或者Constructor對象
- 使用Field對象或者Method對象或者Constructor對象調用實現的Member接口的AccessibleObject方法去交訪問權限檢查
- Field對象或者Method對象或者Constructor對象進行反射操作
For Example
有這樣一個類,可以看到其構造器、屬性和方法都是私有的(toString方法是一會兒用來驗證的),普通的手段是無法使用這個類的。
目標類
現在通過反射來使用這個類:
通過反射操作構造器、方法、屬性
最后看一下運行結果:
運行結果
接口整理
看了上面的例子應該對Java反射有了整體的理解。但上面的例子仍舊太簡單了,因為Java反射還提供了很多其他的接口可供調用。
獲取Class對象
上面例子中是一種獲取Class對象的方式,獲取Class對象的方式有很多種:
常見的獲取Class對象的方法
Constructor對象
Class提供4種獲取Constructor對象的方法。
//獲取指定的構造器(任何訪問類型的構造器、注意是可變參數) Class.getDeclaredConstructor(Class<?>... parameterTypes); //獲取指定的public構造器(注意是可變參數) Class.getConstructor(Class<?>... parameterTypes); //獲取所有構造器(任何訪問類型的構造器),返回Constructor數組 Class.getDeclaredConstructors(); //獲取所有public構造器,返回Constructor數組 Class.getConstructors();
Field對象
Class提供4種獲取Field對象的方法。
和獲取Constructor對象類似。
現在再看看上面寫的:
Field類:實現了Member接口。該類針對屬性。該類提供了獲取屬性的類型、修飾符、注解、變量名、值以及修改屬性值的功能(包括private屬性)
例子種修改屬性值是通過set方法實現的。其他提到的這些功能,Field都有相應的方法可供調用。只需簡單查詢接口文檔即可。
獲取Method對象
Class提供4種獲取Method對象的方法。
和獲取Constructor對象類似。
Method類:實現了Member接口。該類針對方法。該類提供了獲取方法返回類型、方法參數類型、方法參數名稱、方法拋出異常類型、方法修飾符,以及通過反射調用方法等功能。
例子中通過反射調用方法使用的是invoke()方法。其他提到的功能,Method都有相應的方法可供調用。只需要簡單的查詢接口文檔即可。