本文来自刘兆贤的博客_CSDN博客-Java高级,Android旅行,Android基础领域博主 ,引用必须注明出处!
Java的注解、反射等机制的产生,让动态代理成为可能,一般通过全限定名+类名,找到类,可以invoke它的构造方法以及其他方法,可以获取它的参数(Field)名称和值。
注解一般用在代码的注释上、代码审查上(有没有按标准写,比如inspect)、代码注入(hook,asbectj),需要考虑的是,在何时注入(编译期还运行期)
基础反射:获取类的变量名和变量值
public static Map<String, Object> toMap(Object obj) {
Map<String, Object> reMap = new HashMap<>();
Class<?> clz = obj.getClass();//获取此对象运行期的Class对象
while (clz != null) {
Field[] fields = clz.getDeclaredFields();//获得类里声明的变量
for (Field field : fields) {
try {
String fieldName = field.getName();//获得变量名称
if (!extraParam(fieldName)) {
Field f = clz.getDeclaredField(fieldName);
f.setAccessible(true);
Object o = f.get(obj);//获得变量值
reMap.put(fieldName, o);
}
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
clz = clz.getSuperclass();//获得父类的Class对象,继续递归
}
return reMap;
}
private static boolean extraParam(String fieldName) {
//以下三种变量,通常不需要写入
return fieldName.equals("serialVersionUID")//用于根据变量产生,在恢复本地文件时,如果id不同,则类不同,就不需要再恢复(说明缓存已经过期)
|| fieldName.equals("shadow$_klass_")//API20以后出现,运行期对象的Class变量
|| fieldName.equals("shadow$_monitor_");//API20以后出现
}
反射一般用在动态将json和Object互相转化,执行相关底层代码,比如设置某个类的Accessible为false,防止别人hook修改
例:阿里的FastJson解析:
@Override public <T> T json2Object(String json, Class<T> clazz) {
return JSON.parseObject(json, clazz);
}
@Override public String object2Json(Object instance) {
return JSON.toJSONString(instance);
}
例Java的默认注解策略:
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
默认,编译时被抛弃
*/
SOURCE,
/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the defau