ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

反射工具类,如斯优雅,安卓高级开发面试题

2022-01-27 18:30:52  阅读:173  来源: 互联网

标签:面试题 return 安卓 args private 优雅 ReflectUtils type final


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 也是存在这个问题,我也已经对其修复了。

还有就是 jOORprivate static final 字段先 getset 会报异常 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;

标签:面试题,return,安卓,args,private,优雅,ReflectUtils,type,final
来源: https://blog.csdn.net/m0_66264910/article/details/122722084

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有