反射
定義:通過類對象獲取這個(gè)類的屬性,方法,父類,和接口信息
用處:運(yùn)行時(shí)判斷任意一個(gè)對象所屬的類,構(gòu)造一個(gè)對象,動(dòng)態(tài)調(diào)用方法
相關(guān)方法:
getName():獲得類的完整名字。
newInstance():通過類的不帶參數(shù)的構(gòu)造方法創(chuàng)建這個(gè)類的一個(gè)對象。 getFields():獲得類的public類型的屬性。
getDeclaredFields():獲得類的所有屬性。
getMethods():獲得類的public類型的方法。
getDeclaredMethods():獲得類的所有方法。
getMethod(String name, Class[] parameterTypes):獲得類的特定方法。 getModifiers()和Modifier.toString():獲得屬修飾符,例如private,public,static等
getReturnType():獲得方法的返回類型
getParameterTypes():獲得方法的參數(shù)類型
getConstructors():獲得類的public類型的構(gòu)造方法。 getConstructor(Class[] parameterTypes):獲得類的特定構(gòu)造方法。 getSuperclass():獲取某類的父類
getInterfaces():獲取某類實(shí)現(xiàn)的接口
獲取類型:
EatBreckfast eatBreckfast =(EatBreckfast)Class.forName("eatBreckfast").newInstance();
//通過類型絕對路徑直接獲得這個(gè)類,
注解:
定義:與類型,接口,枚舉在同一層次,可以用來描述包類,字段,方法,變量等內(nèi)容
元注解:四個(gè)元注解
1.@Target ???//注解對應(yīng)的使用目標(biāo)
例如:@Target(ElementType.METHOD)//表示該注解應(yīng)用于方法
2.@Retention ?//留住類型 ??表示這個(gè)注解生效的生命周期
@Retention(RetentionPolicy.RUNTIME)//運(yùn)行時(shí)
3.@Documented:是一個(gè)標(biāo)記注解,用來描述其他類型的注解應(yīng)該被作為被標(biāo)注的程序成員的公共api,因此可以被javadoc之類的工具文檔化。
4.@Inherited:也是一個(gè)標(biāo)記注解,他表示某個(gè)被標(biāo)注的類型是可以被繼承的
定義格式:
public @interface注解名{}
例如
public@interfaceAddLog{
StringdialogContent()default"";// 可以理解為注解的字段?
}
注解的參數(shù)字段支持8種基本類型int float boolean byte double char long short String Class enum Annotation
結(jié)合動(dòng)態(tài)代理寫了個(gè)例子
首先是根據(jù)對象獲取類型
/***獲取傳入?yún)?shù)對象的類型*@paramarg*@return*@throwsException*/
privateClass[]getClassArray(Object[] arg)throwsException {
if(arg!=null&&arg.length>0){
Class[] classArray=newClass[arg.length];
for(inti=0;i
classArray[i]=arg[i].getClass();
}
returnclassArray;
}else{
throw newException("invaild param type !");
}
}
四個(gè)點(diǎn):
動(dòng)態(tài)參數(shù),線程池,反射和注解
**@paramtClass*@parammethodName*@paramarg*@throwsException*/public voidrunOnThread(finalClass tClass,String methodName,finalObject...arg)throwsException {
Class[] classeArray=getClassArray(arg);
finalMethod method =tClass.getMethod(methodName,classeArray);
pool.execute(newRunnable() {
@Override
public voidrun() {
/*** 在這里加入預(yù)處理*/method.setAccessible(true);
try{
AddLogaddLogAnnotation =method.getAnnotation(AddLog.class);
if(!TextUtils.isEmpty(addLogAnnotation.dialogContent())){
Log.e(TAG,"this is addlog,this will show befor invoke "+addLogAnnotation.dialogContent());
}
method.invoke(tClass.newInstance(),arg);//調(diào)用代理的方法
Log.e(TAG,"this is a test don't use annotion dynamicProxy ");
}catch(Exception e) {
e.printStackTrace();
}
}
});
}
動(dòng)態(tài)參數(shù):
方法定義使用了動(dòng)態(tài)參數(shù)(java1.5引入) 定義格式(Class...arg) 動(dòng)態(tài)參數(shù)必須是最后一個(gè)參數(shù)或者唯一參數(shù),然后動(dòng)態(tài)參數(shù)的類型必須是相同的,實(shí)際上這個(gè)動(dòng)態(tài)參數(shù)可以看做是一個(gè)list但是 省去了穿入?yún)?shù)的時(shí)候的拼裝過程,在這里我們通過上前面的getClassArray來獲取數(shù)據(jù)的類型因此使用了Object來做為數(shù)據(jù)類型這樣我們可以傳入任何數(shù)據(jù)類型,算是投機(jī)取巧吧(不知道這樣會(huì)不會(huì)有其他不良后果), 這樣使用動(dòng)態(tài)參數(shù)有一個(gè)顯而易見的風(fēng)險(xiǎn),如果調(diào)用這個(gè)方法的重載或者使用反射來獲取方法名如下文
finalMethod method =tClass.getMethod(methodName,classeArray);
這樣如果有多個(gè)匹配參數(shù)的方法會(huì)導(dǎo)致編譯失敗,所以應(yīng)該避免使用類型不明確的方式去調(diào)用方法
finalMethod method =tClass.getMethod(methodName,classeArray);
這句也是用類型反射獲取方法
AddLogaddLogAnnotation =method.getAnnotation(AddLog.class);
這樣表示獲取方法的注解然后我們可以根據(jù)獲取到的注解作出相應(yīng)的操作,例如原文中我們將注解:
@AddLog
上的dialogContent內(nèi)容打成日志
然后,over!