日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

反射工具类,如斯优雅

發布時間:2025/3/19 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 反射工具类,如斯优雅 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Foreword

反射的作用我在這就不多說了,每次用到反射都是那么一坨代碼丟進去,總是讓人覺得很不優雅,如今有了我這個反射工具類,那么大家就可以一句話優雅地來完成反射的工作,該工具類是站在 jOOR 的肩膀上進行改造,修復了它沒有完成的工作,至于修復了什么,后面源碼分析會詳述,至于這個工具類在哪,現已加入至 1.12.0 版本的 AndroidUtilCode,下面來介紹下其功能。

Functions

其 APIs 如下所示:

反射相關 -> ReflectUtils.java -> Test

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()); 復制代碼

設置反射的方法

比如,我們想要調用 String 的 substring 函數可以這樣做:

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 值為 2assertEquals(2, Test1.S_INT1);// 靜態變量就是最后設置的 2assertEquals(null, Test1.S_INT2);// 沒操作過就是 nullassertEquals(0, Test1.S_DATA.I_INT1);// 沒操作過就是 0assertEquals(null, Test1.S_DATA.I_INT2);// 沒操作過就是 0assertEquals(1, Test1.S_DATA.I_DATA.I_INT1);// 倒數第二步操作設置為 1assertEquals(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<?>>() {@Overridepublic 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(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);} }/*** 設置反射的字段** @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; } 復制代碼

所以該工具類既完美支持 Java,也完美支持 Android。

Conclusion

好了,這次反射工具類就介紹到這了,是不是覺得如斯優雅,如果覺得好的話以后遇到反射的問題,那就快用我這個工具類吧,這么好的東西藏著不用真的是可惜了哦。

關于安卓核心常用工具類我已經差不多都封裝了,今后應該也不會在核心的里面新增了,除非確實很需要我才會再新增某個工具類,其余不常用的我都會放在 subutil 中,感謝大家一直陪伴著 AndroidUtilCode 的成長。

總結

以上是生活随笔為你收集整理的反射工具类,如斯优雅的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 一级黄视频| youjizz.com最新| 黄色麻豆视频 | 国产一卡二卡三卡四卡 | 5566在线| 国产美女被遭强高潮免费网站 | 天天干天天干 | 91视频在| 尤物精品视频在线观看 | 久久久久久久久久网 | 自拍偷拍国产 | 国产精品一区二区三区在线免费观看 | 久久一视频 | 性感美女被爆操 | 日韩av一区二区三区四区 | 天躁夜夜躁狼狠躁 | 国产精品久久久无码一区 | 亚洲制服丝袜一区 | 欧洲久久久久 | av一区二区三区免费观看 | 久久久久99精品成人片试看 | 美女扒开腿免费视频 | 99热亚洲| 婷婷综合精品 | 亚洲色图丝袜 | 午夜国产一区 | 日韩精品视频一区二区三区 | 日本黄色小网站 | 国产精品女同 | 国产伦精品一区二区三区精品 | 欧美成人vr18sexvr | 白嫩初高中害羞小美女 | 怡红院av在线 | 精品人妻一区二区三区四区久久 | 国产精品三级在线观看无码 | 丁香花电影免费播放电影 | 爱爱91 | 欧美一级视频免费 | www.97av| 国产盗摄一区二区三区在线 | 亚洲色图自拍 | 亚洲欧美日韩国产综合 | 欧美激情在线播放 | 俺啪也| 伊人免费在线观看高清版 | 国产在线精 | 亚洲第一成网站 | 久久久久中文字幕亚洲精品 | 在线a网站 | 台湾性dvd性色av | 久久午夜视频 | 97人人在线 | 日韩欧美视频 | 黄色片成年人 | 久久合合 | 一本色道久久综合亚洲精品小说 | 日美毛片| 美女脱了内裤喂我喝尿视频 | 久久久av免费 | 成人一区二区三区在线 | 女同毛片一区二区三区 | 亚洲第5页 | 麻豆视频污 | 黄色小网站在线观看 | 国产91一区二区三区在线精品 | 高h av | 成人av高清在线观看 | 蜜臀人妻四季av一区二区不卡 | 久久久久性 | 亚洲一区二区蜜桃 | 国产精品区在线观看 | 日本在线观看视频网站 | 欧美另类视频 | 8090理论片午夜理伦片 | 国产免费三片 | 四虎在线精品 | 一区二区三区免费在线观看视频 | 一区一区三区产品乱码 | 在线观看免费高清视频 | 亚洲精品一区二区三区不卡 | 亚洲AV无码成人精品区麻豆 | 国产精品videossex久久发布 | 亚洲人成色777777老人头 | 欧美成年人视频 | 精品视频在线观看 | 黄视频在线免费 | 欧美日韩国产三级 | 欧美一区二区网站 | 亚洲欧美自拍另类 | 国产精品99久久久精品无码 | 一区二区三区在线免费播放 | 最新永久地址 | 久久国产福利 | 日本xx视频 | 黄色不打码视频 | 久久黄色精品视频 | 亚洲av无码一区二区三区在线观看 | 欧美brazzers| 狠狠爱视频|