今天突然想到原先写过的一个反射类的效率问题,通过测试发现反射获取值的时间为直接获取值时间的9倍左右,于是加一个map缓存一部分结果,效率获得明显的提升取值时间大概为直接取值的三倍左右。
测试代码不贴了
测试结果
循环100000次
反射:890ms左右
加入map:300ms左右
直接调用:100ms左右
下面贴出改进代码
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
public class ReflectHelper {
private static Map<Class<?>, Map<String, Field>> map = new HashMap<Class<?>, Map<String, Field>>();
/**
* 获取obj对象fieldName的Field
*
* @param obj
* @param fieldName
* @return
*/
public static Field getFieldByFieldName(Object obj, String fieldName) {
Class<?> objClass = obj.getClass();
Map<String, Field> cMap = map.get(objClass);
if (cMap != null) {
Field f = cMap.get(fieldName);
if (f != null) {
return f;
}
} else {
cMap = new HashMap<String, Field>();
map.put(objClass, cMap);
}
for (Class<?> superClass = objClass; superClass != Object.class; superClass = superClass.getSuperclass()) {
try {
Field field = superClass.getDeclaredField(fieldName);
cMap.put(fieldName, field);
return field;
} catch (NoSuchFieldException e) {
}
}
return null;
}
/**
* 获取obj对象fieldName的属性值
*
* @param obj
* @param fieldName
* @return
* @throws SecurityException
* @throws NoSuchFieldException
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
public static Object getValueByFieldName(Object obj, String fieldName) throws SecurityException,
NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
Field field = getFieldByFieldName(obj, fieldName);
Object value = null;
if (field != null) {
if (field.isAccessible()) {
value = field.get(obj);
} else {
field.setAccessible(true);
value = field.get(obj);
field.setAccessible(false);
}
}
return value;
}
/**
* 设置obj对象fieldName的属性值
*
* @param obj
* @param fieldName
* @param value
* @throws SecurityException
* @throws NoSuchFieldException
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
public static void setValueByFieldName(Object obj, String fieldName, Object value) throws SecurityException,
NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
Field field = obj.getClass().getDeclaredField(fieldName);
if (field.isAccessible()) {
field.set(obj, value);
} else {
field.setAccessible(true);
field.set(obj, value);
field.setAccessible(false);
}
}
}