String str1 = ReflectUtils.reflect((Object) “1234”).method(“substring”, 2).get();
// equals: String str1 = “1234”.substring(2);
String str2 = ReflectUtils.reflect((Object) “1234”).method(“substring”, 0, 2).get();
// equals: String str1 = “1234”.substring(0, 2);
设置反射的字段
比如,TestPrivateStaticFinal.java
如下所示:
public class TestPrivateStaticFinal {
private static final int I1 = new Integer(1);
private static final Integer I2 = new Integer(1);
}
我们要设置其 I1
、I2
值为 2,可以如下操作:
ReflectUtils.reflect(TestPrivateStaticFinal.class).field(“I1”, 2);
ReflectUtils.reflect(TestPrivateStaticFinal.class).field(“I2”, 2);
要获取其 I1
、I2
值的话,可以如下操作:
ReflectUtils.reflect(TestPrivateStaticFinal.class).field(“I1”).get()
ReflectUtils.reflect(TestPrivateStaticFinal.class).field(“I2”).get()
当然,字段操作也有更高级的操作,比如 Test1.java
测试类如下所示:
public class Test1 {
public static int S_INT1;
public static Integer S_INT2;
public int I_INT1;
public Integer I_INT2;
public static Test1 S_DATA;
public Test1 I_DATA;
}
我对其进行的单元测试如下所示:
@Test
public void fieldAdvanced() throws Exception {
ReflectUtils.reflect(Test1.class)
.field(“S_DATA”, ReflectUtils.reflect(Test1.class).newInstance())// 设置 Test1.class 中 S_DATA 字段 为 new Test1()
.field(“S_DATA”)// 获取到 Test1.class 中 S_DATA 字段
.field(“I_DATA”, ReflectUtils.reflect(Test1.class).newInstance())// 获取到 Test1.class 中 S_DATA 字段 的 I_DATA 为 new Test1()
.field(“I_DATA”)// 获取到 Test1.class 中 S_DATA 字段 的 I_DATA 字段
.field(“I_INT1”, 1)// 设置 Test1.class 中 S_DATA 字段 的 I_DATA 字段的 I_INT1 值为 1
.field(“S_INT1”, 2);// 设置 Test1.class 中 S_DATA 字段 的 S_INT1 字段的 I_INT1 值为 2
assertEquals(2, Test1.S_INT1);// 静态变量就是最后设置的 2
assertEquals(null, Test1.S_INT2);// 没操作过就是 null
assertEquals(0, Test1.S_DATA.I_INT1);// 没操作过就是 0
assertEquals(null, Test1.S_DATA.I_INT2);// 没操作过就是 0
assertEquals(1, Test1.S_DATA.I_DATA.I_INT1);// 倒数第二步操作设置为 1
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
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(Object 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);
}
}
/**
- 设置反射的字段
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
最后
今天关于面试的分享就到这里,还是那句话,有些东西你不仅要懂,而且要能够很好地表达出来,能够让面试官认可你的理解,例如Handler机制,这个是面试必问之题。有些晦涩的点,或许它只活在面试当中,实际工作当中你压根不会用到它,但是你要知道它是什么东西。
最后在这里小编分享一份自己收录整理上述技术体系图相关的几十套腾讯、头条、阿里、美团等公司2021年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。
还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
【Android核心高级技术PDF文档,BAT大厂面试真题解析】
【算法合集】
【延伸Android必备知识点】
【Android部分高级架构视频学习资源】
Android精讲视频领取学习后更加是如虎添翼!进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!