assertEquals(null, Test1.S_DATA.I_DATA.I_INT2);// 没操作过就是 null
}
根据如上注释相信大家也可以理解一二了,如果还想了解更多使用方式,可以查看我写的单元测试类 ReflectUtilsTest,其使用方式就介绍到这里,下面介绍其实现方式。
Achieve
实现的话是站在 jOOR 的肩膀上进行改造,其内部封装了一个 private final Object object;
变量,每次进行反射操作时都会重新实例化一个变量并把结果赋予该变量,最终 get()
就是获取其值,比如我们来看一下 newInstance
的操作,其涉及的代码如下所示:
/**
- 实例化反射对象
- @param args 实例化需要的参数
- @return {@link ReflectUtils}
*/
public ReflectUtils newInstance(Object… args) {
Class<?>[] types = getArgsType(args);
try {
Constructor<?> constructor = type().getDeclaredConstructor(types);
return newInstance(constructor, args);
} catch (NoSuchMethodException e) {
List<Constructor<?>> list = new ArrayList<>();
for (Constructor<?> constructor : type().getDeclaredConstructors()) {
if (match(constructor.getParameterTypes(), types)) {
list.add(constructor);
}
}
if (list.isEmpty()) {
throw new ReflectException(e);
} else {
sortConstructors(list);
return newInstance(list.get(0), args);
}
}
}
private Class<?>[] getArgsType(final Object… args) {
if (args == null) return new Class[0];
Class<?>[] result = new Class[args.length];
for (int i = 0; i < args.length; i++) {
Object value = args[i];
result[i] = value == null ? NULL.class : value.getClass();
}
return result;
}
private void sortConstructors(List<Constructor<?>> list) {
Collections.sort(list, new Comparator<Constructor<?>>() {
@Override
public int compare(Constructor<?> o1, Constructor<?> o2) {
Class<?>[] types1 = o1.getParameterTypes();
Class<?>[] types2 = o2.getParameterTypes();
int len = types1.length;
for (int i = 0; i < len; i++) {
if (!types1[i].equals(types2[i])) {
if (wrapper(types1[i]).isAssignableFrom(wrapper(types2[i]))) {
return 1;
} else {
return -1;
}
}
}
return 0;
}
});
}
private ReflectUtils newInstance(final Constructor<?> constructor, final Object… args) {
try {
return new ReflectUtils(
constructor.getDeclaringClass(),
accessible(constructor).newInstance(args)
);
} catch (Exception e) {
throw new ReflectException(e);
}
}
private final Class<?> type;
private final Object object;
private ReflectUtils(final Class<?> type, Object object) {
this.type = type;
this.object = object;
}
jOOR 所没有做到的就是没有对多个符合的 Constructor
进行排序,而是直接返回了第一个与之匹配的。这样说有点抽象,我举个例子应该就明白了,比如说有两个构造函数如下所示:
public class Test {
public Test(Number n) {
}
public Test(Object n) {
}
}
jOOR 反射调用构造函数参数传入 Long
类型,很可能就会走 Test(Obj![](https://www.hualigs.cn/image/61dba891ed8ee.jpg) ect n)
这个构造函数,而我修改过后就是对多个符合的 Constructor
进行排序,匹配出与之最接近的父类,也就是会走 Test(Number n)
这个构造函数,同理,在后面的 method
中的参数匹配 jOOR 也是存在这个问题,我也已经对其修复了。
还有就是 jOOR 对 private static final
字段先 get
再 set
会报异常 java.lang.IllegalAccessException
异常,是因为对 private static final
字段 get
的时候没有去除 final
属性,如果在 get
时就把 final
去掉即可解决,那样在 set
的时候就不会报错。然而,在 Android 的 SDK 中是没有 Field.class.getDeclaredField("modifiers")
这个字段的,所以会报 NoSuchFieldException
异常,这方面我做了容错处理,相关代码如下所示:
/**
- 设置反射的字段
- @param name 字段名
- @return {@link ReflectUtils}
*/
public ReflectUtils field(final String name) {
try {
Field field = getField(name);
return new ReflectUtils(field.getType(), field.get(object));
} catch (IllegalAccessException e) {
throw new ReflectException(e);
}
}
/**
- 设置反射的字段
- @param name 字段名
- @param value 字段值
- @return {@link ReflectUtils}
*/
public ReflectUtils field(String name, Object value) {
try {
Field field = getField(name);
field.set(object, unwrap(value));
return this;
} catch (Exception e) {
throw new ReflectException(e);
}
}
private Field getField(String name) throws IllegalAccessException {
Field field = getAccessibleField(name);
if ((field.getModifiers() & Modifier.FINAL) == Modifier.FINAL) {
try {
Field modifiersField = Field.class.getDeclaredField(“modifiers”);
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
} catch (NoSuchFieldException ignore) {
// runs in android will happen
}
}
return field;
}
private Field getAccessibleField(String name) {
Class<?> type = type();
try {
return accessible(type.getField(name));
} catch (NoSuchFieldException e) {
do {
try {
return accessible(type.getDeclaredField(name));
} catch (NoSuchFieldException ignore) {
}
type = type.getSuperclass();
} while (type != null);
throw new ReflectException(e);
}
}
private Object unwrap(Object object) {
if (object instanceof ReflectUtils) {
return ((ReflectUtils) object).get();
}
return object;