反射工具类,如斯优雅

reflect : 设置要反射的类
newInstance: 实例化反射对象
field : 设置反射的字段
method : 设置反射的方法
get : 获取反射想要获取的

Use

实例化反射对象

比如,我们实例化一个 String 对象可以这样做:

String str1 = ReflectUtils.reflect(String.class).newInstance().get();
// equals: String str1 = new String();

String str2 = ReflectUtils.reflect(“java.lang.String”).newInstance(“abc”).get();
// equals: String str2 = new String(“abc”);

String str3 = ReflectUtils.reflect(String.class).newInstance(“abc”.getBytes()).get();
// equals: String str3 = new String(“abc”.getBytes());

设置反射的方法

比如,我们想要调用 Stringsubstring 函数可以这样做:

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);
}

我们要设置其 I1I2 值为 2,可以如下操作:

ReflectUtils.reflect(TestPrivateStaticFinal.class).field(“I1”, 2);
ReflectUtils.reflect(TestPrivateStaticFinal.class).field(“I2”, 2);

要获取其 I1I2 值的话,可以如下操作:

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

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助

因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
d开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门**

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

  • 27
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值