在計(jì)算機(jī)科學(xué)中膘壶,反射是指計(jì)算機(jī)程序在運(yùn)行時(shí)(Run time)可以訪問春畔、檢測和修改它本身狀態(tài)或行為的一種能力拌牲。[1]用比喻來說,反射就是程序在運(yùn)行的時(shí)候能夠“觀察”并且修改自己的行為驻啤。
Java 反射主要提供以下功能:
在運(yùn)行時(shí)判斷任意一個(gè)對(duì)象所屬的類;
在運(yùn)行時(shí)構(gòu)造任意一個(gè)類的對(duì)象喉恋;
在運(yùn)行時(shí)判斷任意一個(gè)類所具有的成員變量和方法(通過反射甚至可以調(diào)用private方法);
在運(yùn)行時(shí)調(diào)用任意一個(gè)對(duì)象的方法
// 即以下方法都屬于Class
類的方法梭域。
<-- 1. 獲取類的構(gòu)造函數(shù)(傳入構(gòu)造函數(shù)的參數(shù)類型)->>
// a. 獲取指定的構(gòu)造函數(shù) (公共 / 繼承)
Constructor<T> getConstructor(Class<?>... parameterTypes)
// b. 獲取所有的構(gòu)造函數(shù)(公共 / 繼承)
Constructor<?>[] getConstructors();
// c. 獲取指定的構(gòu)造函數(shù) ( 不包括繼承)
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
// d. 獲取所有的構(gòu)造函數(shù)( 不包括繼承)
Constructor<?>[] getDeclaredConstructors();
// 最終都是獲得一個(gè)Constructor類對(duì)象
// 特別注意:
// 1. 不帶 "Declared"的方法支持取出包括繼承、公有(Public) & 不包括有(Private)的構(gòu)造函數(shù)
// 2. 帶 "Declared"的方法是支持取出包括公共(Public)搅轿、保護(hù)(Protected)病涨、默認(rèn)(包)訪問和私有(Private)的構(gòu)造方法,但不包括繼承的構(gòu)造函數(shù)
// 下面同理
<-- 2. 獲取類的屬性(傳入屬性名) -->
// a. 獲取指定的屬性(公共 / 繼承)
Field getField(String name) ;
// b. 獲取所有的屬性(公共 / 繼承)
Field[] getFields() ;
// c. 獲取指定的所有屬性 (不包括繼承)
Field getDeclaredField(String name) 璧坟;
// d. 獲取所有的所有屬性 (不包括繼承)
Field[] getDeclaredFields() 既穆;
// 最終都是獲得一個(gè)Field類對(duì)象
<-- 3. 獲取類的方法(傳入方法名 & 參數(shù)類型)-->
// a. 獲取指定的方法(公共 / 繼承)
Method getMethod(String name, Class<?>... parameterTypes) ;
// b. 獲取所有的方法(公共 / 繼承)
Method[] getMethods() 雀鹃;
// c. 獲取指定的方法 ( 不包括繼承)
Method getDeclaredMethod(String name, Class<?>... parameterTypes) 幻工;
// d. 獲取所有的方法( 不包括繼承)
Method[] getDeclaredMethods() ;
// 最終都是獲得一個(gè)Method類對(duì)象
<-- 4. Class類的其他常用方法 -->
getSuperclass();
// 返回父類
String getName();
// 作用:返回完整的類名(含包名黎茎,如java.lang.String )
Object newInstance();
// 作用:快速地創(chuàng)建一個(gè)類的實(shí)例
// 具體過程:調(diào)用默認(rèn)構(gòu)造器(若該類無默認(rèn)構(gòu)造器会钝,則拋出異常
// 注:若需要為構(gòu)造器提供參數(shù)需使用java.lang.reflect.Constructor中的newInstance()
通過 Class 對(duì)象分別獲取Constructor類對(duì)象、Method類對(duì)象 & Field 類對(duì)象
Class<?> serviceManager = null;
try {
serviceManager = Class.forName("android.os.ServiceManager");
System.out.println(serviceManager);
//獲取方法
Method getService = serviceManager.getMethod("getService", String.class);
//調(diào)用方法
IBinder iBinder = (IBinder) getService.invoke(serviceManager.newInstance(), "InputService");
System.out.println(iBinder);
} catch (Exception e) {
e.printStackTrace();
}
getDeclaredMethod*()獲取的是類自身聲明的所有方法工三,包含public、protected和private方法先鱼。
getMethod*()獲取的是類的所有共有方法俭正,這就包括自身的所有public方法,和從基類繼承的焙畔、從接口實(shí)現(xiàn)的所有public方法掸读。
小技巧 :getDeclaredMethods的效率高,但是只能查詢自身的類方法宏多,如果沒找到可以再次嘗試getMethods()獲得
如下參考EventBus中 SubscriberMethodFinder.java部分片段:
try {
// This is faster than getMethods, especially when subscribers are fat classes like Activities
methods = findState.clazz.getDeclaredMethods();
} catch (Throwable th) {
// Workaround for java.lang.NoClassDefFoundError, see https://github.com/greenrobot/EventBus/issues/149
methods = findState.clazz.getMethods();
findState.skipSuperClasses = true;
}