“反射”(Reflection)能夠讓運(yùn)行于JVM中的程序檢測(cè)和修改運(yùn)行時(shí)的行動(dòng)。
反射帶來(lái)的好處包括:
聲明以下:
public Method getDeclaredMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException
解釋:
返回1個(gè)Method對(duì)象,該對(duì)象反應(yīng)此Class對(duì)象所表示的類或接口的指定已聲明方法。
1. name : 是1個(gè)String,它指定所需方法的簡(jiǎn)稱。
2. parameterTypes:是1個(gè)Class對(duì)象的變長(zhǎng)數(shù)組,它按聲明順序標(biāo)識(shí)該方法的形參類型。
注意:
getDeclaredMethod獲得該類聲明的public方法或protected方法,但是不包括繼承的方法。
聲明以下:
public Method getMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException
解釋:
返回1個(gè)Method對(duì)象,該對(duì)象反應(yīng)此Class對(duì)象所表示的類或接口的指定公共成員方法。
1. name : 是1個(gè)String,它指定所需方法的簡(jiǎn)稱。
2. parameterTypes:是1個(gè)Class對(duì)象的變長(zhǎng)數(shù)組,它按聲明順序標(biāo)識(shí)該方法的形參類型。
name參數(shù)就不需要解釋了,就是調(diào)用類的方法名稱。
可能很多同學(xué)剛接觸這個(gè)方法的時(shí)候,會(huì)對(duì)parameterTypes參數(shù)產(chǎn)生疑問(wèn),例如這個(gè)參數(shù)為何是Class泛型變長(zhǎng)數(shù)組,其實(shí)舉個(gè)例子就很好理解了。
假定我們要反射的方法有4個(gè)參數(shù),函數(shù)原型以下:
public void printInfo(String str, int iNum, double dNum, long i);
那我們通過(guò)返回獲得這個(gè)Method對(duì)象的時(shí)候,傳的parameterTypes以下所示:
getMethod("printInfo", String.class, int.class, double.class, long.class);
所以,parameterTypes其實(shí)就是對(duì)方法形參的類型抽象。
聲明以下:
public Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException
解釋:
Method類的invoke(Object obj, Object… args)方法接收的參數(shù)必須為對(duì)象。其中:
1. obj : 從中調(diào)用底層方法的對(duì)象。
2. args :用于方法調(diào)用的參數(shù)。
我們知道,Android有些類是沒(méi)有在SDK中開(kāi)放的,例如你需要獲得系統(tǒng)屬性,需要調(diào)用到SystemProperties類的get方法,但是這個(gè)類并沒(méi)有在SDK中公然,我們可以在Android源碼中查看1下這個(gè)類:
package android.os;
import java.util.ArrayList;
import android.util.Log;
/**
* Gives access to the system properties store. The system properties
* store contains a list of string key-value pairs.
*
* {@hide}
*/
public class SystemProperties
{
// 省略具體實(shí)現(xiàn)代碼
/**
* Get the value for the given key.
* @return an empty string if the key isn't found
* @throws IllegalArgumentException if the key exceeds 32 characters
*/
public static String get(String key) {
if (key.length() > PROP_NAME_MAX) {
throw new IllegalArgumentException("key.length > " + PROP_NAME_MAX);
}
return native_get(key);
}
}
可以看到,這個(gè)前面有1個(gè)@hide標(biāo)簽,所以這個(gè)類是沒(méi)法直接在代碼中調(diào)用的。
但是,在Android利用中,很多時(shí)候我們需要獲得得手機(jī)類型屬性(ro.product.model)。所以,這個(gè)時(shí)候,我們就需要在利用層反射SystemProperties類,調(diào)用get方法。具體實(shí)現(xiàn)源碼以下:
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import android.util.Log;
public class SystemProperties {
public static String get(String key) {
String value = "";
Class<?> cls = null;
try {
cls = Class.forName("android.os.SystemProperties");
Method hideMethod = cls.getMethod("get", String.class);
Object object = cls.newInstance();
value = (String) hideMethod.invoke(object, key);
} catch (ClassNotFoundException e) {
Log.e("zhengyi.wzy", "get error() ", e);
} catch (NoSuchMethodException e) {
Log.e("zhengyi.wzy", "get error() ", e);
} catch (InstantiationException e) {
Log.e("zhengyi.wzy", "get error() ", e);
} catch (IllegalAccessException e) {
Log.e("zhengyi.wzy", "get error() ", e);
} catch (IllegalArgumentException e) {
Log.e("zhengyi.wzy", "get error() ", e);
} catch (InvocationTargetException e) {
Log.e("zhengyi.wzy", "get error() ", e);
}
return value;
}
}