反射機制與Class類
阿新 • • 發佈:2018-11-12
從這節課開始, 我們正式進入java 反射機制的學習
首先,什麼是java的反射機制?來看百度百科:
重點:
- 在執行狀態中
- 對任意一個實體類
- 對任意一個物件
- 動態獲取資訊
- 動態呼叫物件方法
Java有個包,叫java.lang.reflect,這個包下的所有類都是為反射機制服務的,除此之外還有一個非常重要的類:java.lang.Class
public final class Class<T> implements java.io.Serializable, GenericDeclaration,Type, AnnotatedElement {
Class類:
- 反射機制的核心類,這個類包含了我們定義的類的所有屬性和方法以及類名
- 這個類的構造器是私有的,所以不用想著new了
- 獲取Class物件的方法有 類.class,物件.getClass(), Class.forName(String className) 等
接下來來看看程式碼:
package reflection; import helloworld.MyArrayList; import java.lang.reflect.Field; public class ClassTeach { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException { /** * Class類可以動態獲取任意實體類的屬性和方法,那麼,我們隨便挑個類來試試 * 比如之前我們自己寫過的MyArrayList */ //第一種獲取Class物件的方法: 類.class Class clazz1 = MyArrayList.class; //第二種獲取Class物件的方法: 物件.getClass() MyArrayList<Object> list = new MyArrayList<>(); Class clazz2 = list.getClass(); //第三種獲取Class物件的方法: Class.forName() 引數是全類名,即完整包名+類名 //這個方法可能會丟擲ClassNotFoundException,表示要載入的類找不到,這個異常是編譯時異常 Class clazz3 = Class.forName("helloworld.MyArrayList"); /** * 根據百科裡的內容,反射機制是可以動態獲取一個類的所有屬性和方法的 * 我們來試試 * 首先,查API文件,看看有什麼方法可以獲取屬性和方法 * * public Field getDeclaredField(String name) * 返回一個Field物件,它反映此表示的類或介面的指定已宣告欄位類物件。 name引數是一個String ,它指定了所需欄位的簡單名稱。 * * OK,這裡又牽扯出一個新的類 Field,大家可以暫停視訊猜猜在哪個包下 * 揭曉答案, 在java.lang.reflect下,看英語我肯定看得懂,怕你們看不懂,還是來看API文件 * * Filed 提供有關類或介面的單個欄位的資訊和動態訪問。 反射的欄位可以是類(靜態)欄位或例項欄位。 * 所謂欄位,其實就是屬性 */ //用clazz1來試試獲取屬性 //MyArrayList裡有一個size屬性,來獲取的看看 //此方法可能報一個異常NoSuchFieldException,表示沒有這樣的一個屬性 Field sizeField = clazz1.getDeclaredField("size"); System.out.println(sizeField.getName()); //size /** * 來介紹下Field比較常用的三個方法 * getName() 獲取屬性名稱 * set(Object obj, Object value) 給obj的Field對應的屬性賦值value * get(Object obj) 獲取obj的Field對應的屬性的值 */ //前面我們new了一個list物件,現在來試試 //set方法會報一個異常IllegalAccessException,表示非法接觸異常,即如果物件是private的你是不能直接接觸的 //剛說完可能報異常立馬報了,因為size屬性是私有的 //如果我們非要給size屬性賦值怎麼辦? //設定accessible為true即可 sizeField.setAccessible(true); sizeField.set(list,2); //不報錯了 //現在來看看list的size屬性的值 System.out.println(list.size()); //可以看到已經給list的size屬性賦值了 //再來用引用獲取的看看 //get方法依然會拋異常,而且還是兩個 IllegalArgumentException, IllegalAccessException //一個非法引數,一個非法接觸 System.out.println(sizeField.get(list)); //可以看到通過get也可以動態獲取 //最後來輸出下Class對應的類的名字吧,下節課再來講動態獲取方法 System.out.println(clazz1.getName()); //helloworld.MyArrayList } }