JobPlus知识库 互联网 系统架构 文章
Java高级特性之反射学习总结

老规矩我们还是先提出几个问题,一门技术必然要能解决一定的问题,才有去学习掌握它的价值

· 一、 什么是反射?

· 二、反射能做什么?

一、 什么是反射?

用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。

如果你是一个Android Developer,前辈们都会教导你尽量少用反射,效率太低,太慢。“射”嘛,射的太快就不好了,所以反射虽然慢点,但是偶尔射一下还是很”爽”的。

二、反射能做什么?

1、新建类的实例

我们知道所有的类都继承子顶级父类Object,而Object中有hashCode()、equals()、clone()、toString()、getClass()等。其中getClass()返回一个Class 对象。我们这里就需要使用的Class对象,注意C是大写,我们可以通过一下方式来获取Class对象

1. Class.forName(“类名字符串”) (注意:类名字符串必须是全称,包名+类名)

2. 类名.class

3. 实例对象.getClass()

在Class类中有一个非常重要的方法

1. public T newInstance() throws InstantiationException, IllegalAccessException { 

2.        return newInstanceImpl(); 

3.    } 

4.  

5. private native T newInstanceImpl() throws IllegalAccessException, InstantiationException;  

查看Api可以看到调用newInstace方法可以返回当前class对应的实例对象。接下来看一个小的Demo

1. public class Reflection { 

2.  

3.     public static void main(String[] args) { 

4.  

5.         // 普通创建类的实例 

6.  

7.         People p1 = new People(); 

8.         System.out.println(p1.getName()); 

9.         // 利用反射获取类的实例 

10.         Class clazz = People.class; 

11.         // 常用方式,注意括号中需要放类的全路径名 

12.         // Class clazz = Class.forName("reflection.People"); 

13.         // Class clazz = p1.getClass(); 

14.         try { 

15.             People p2 = (People) clazz.newInstance(); 

16.             System.out.println(p2.getName()); 

17.         } catch (Exception e) { 

18.             e.printStackTrace(); 

19.         } 

20.  

21.     } 

22.  

23. } 

24.  

25. class People { 

26.  

27.     private String name = "张三"; 

28.     private int age; 

29.  

30.     public String getName() { 

31.         return name

32.     } 

33.  

34.     public void setName(String name) { 

35.         this.name = name

36.     } 

37.  

38.     public int getAge() { 

39.         return age; 

40.     } 

41.  

42.     public void setAge(int age) { 

43.         this.age = age; 

44.     } 

45.  

46. }  

输入结果:

1. 张三 

2.  张三  

2、获取成员变量和方法

在讲之前我们先来看这样一个小按理,JSON数据转JavaBaen对象,在不用解析库的情况下,一般我们会这样做

1. private void analysisDate(JSONObject response) throws JSONException { 

2.         int announceid = response.getInt("announceid"); 

3.         String title = response.getString("title"); 

4.         String hits = response.getString("hits"); 

5.         String addtime = response.getString("addtime"); 

6.         NewsNotifyItem newsNotifyItem = new NewsNotifyItem(announceid, 

7.                 title, hits, addtime); 

8.     } 

9. }  

每当我们需要解析额时候,都需要根据不同javabean来进行相应的解析,我们每次进行的操作都是一样的,只是解析的数据不同而已,结合上篇帖子讲到的泛型,这里我们就可以再利用反射来自己做一个Json解析工具。

下面是我写的一个JsonObject对象转JavaBean的一个工具类,需要注意的是,JSON的key需要和字段名保持一致,先说下思路

①首先通过反射获取JavaBean中的所有字段值的名称

②拼接出set方法

③由于字段名和Json的key值相同,利用自动名获取Json中的值并填充的实例对象中

1. public class Json2BeanUtils { 

2.  

3.     public static <T> T jsonToBean(JSONObject response, Class<T> clazz) { 

4.         try { 

5.             // 创建类的实例 

6.             Object object = Class.forName(clazz.getName()).newInstance(); 

7.             // 获取类中的所有成员变量 

8.             Field[] fields = object.getClass().getDeclaredFields(); 

9.             for (int i = 0; i < fields.length; i++) { 

10.                 //设置权限 

11.                 fields[i].setAccessible(true); 

12.                 // 获取字段的名称 

13.                 String fieldName = fields[i].getName(); 

14.                 // 过滤掉UID 

15.                 if (fieldName.endsWith("serialVersionUID")) { 

16.                     continue

17.                 } 

18.                 // 获取字段的类型 

19.                 String fieldType = fields[i].getGenericType().toString(); 

20.                 // 拼接出JavaBean中的set方法 这里有一个坑 后面讲解 

21.                 String methodName = "set" 

22.                         + fieldName.substring(0, 1).toUpperCase() 

23.                         + fieldName.substring(1); 

24.                 try { 

25.                     // 判断变量类型 

26.                     if (fieldType.endsWith("class java.lang.String")) { 

27.                         // 获取到set方法 

28.                         Method m = object.getClass().getMethod(methodName, 

29.                                 String.class); 

30.                         String value = null; 

31.                         try { 

32.                             // 从JsonObj中取出相应的值 

33.                             value = response.getString(fieldName); 

34.                         } catch (Exception e) { 

35.                             e.printStackTrace(); 

36.                             value = ""; 

37.                         } 

38.                         if (TextUtils.isEmpty(value)) { 

39.                             value = ""; 

40.                         } else if (value.endsWith("null")) { 

41.                             value = ""; 

42.                         } 

43.                         // 赋值 

44.                         m.invoke(object, value); 

45.                     } else if (fieldType.endsWith("int") 

46.                             || fieldType.endsWith("class java.lang.Integer")) { 

47.                         // int 类型 

48.                         System.out.println(); 

49.                         Method m = object.getClass().getMethod(methodName, 

50.                                 int.class); 

51.                         int value = -1; 

52.                         try { 

53.                             value = response.getInt(fieldName); 

54.                         } catch (Exception e) { 

55.                             e.printStackTrace(); 

56.                             value = -1; 

57.                         } 

58.                         m.invoke(object, value); 

59.  

60.                     } else if (fieldType.endsWith("boolean") 

61.                             || fieldType 

62.                                     .endsWith("fieldType:class java.lang.Boolean")) { 

63.                         // boolean 类型 

64.                         Method m = object.getClass().getMethod(methodName, 

65.                                 boolean.class); 

66.                         boolean value = false

67.                         try { 

68.                             value = response.getBoolean(fieldName); 

69.                         } catch (Exception e) { 

70.                             e.printStackTrace(); 

71.                             value = false

72.                         } 

73.                         m.invoke(object, value); 

74.                     } else if (fieldType.endsWith("double") 

75.                             || fieldType 

76.                                     .endsWith("fieldType:class java.lang.Double")) { 

77.                         // double 类型 

78.                         Method m = object.getClass().getMethod(methodName, 

79.                                 double.class); 

80.                         double value = -1D; 

81.                         try { 

82.                             value = response.getDouble(fieldName); 

83.                         } catch (Exception e) { 

84.                             e.printStackTrace(); 

85.                             value = -1D; 

86.                         } 

87.                         m.invoke(object, value); 

88.                     } else if (fieldType.endsWith("char")) { 

89.                         // char类型 JSONObject 没有char 

90.                         Method m = object.getClass().getMethod(methodName, 

91.                                 String.class); 

92.                         String value = ""; 

93.                         try { 

94.                             value = response.getString(fieldName); 

95.                         } catch (Exception e) { 

96.                             e.printStackTrace(); 

97.                             value = ""; 

98.                         } 

99.                         m.invoke(object, value); 

100.                     } else if (fieldType.endsWith("float") 

101.                             || fieldType 

102.                                     .endsWith("fieldType:class java.lang.Float")) { 

103.                         // float类型 

104.                         Method m = object.getClass().getMethod(methodName, 

105.                                 double.class); 

106.                         double value = -1D; 

107.                         try { 

108.                             value = response.getDouble(fieldName); 

109.                         } catch (Exception e) { 

110.                             e.printStackTrace(); 

111.                             value = -1D; 

112.                         } 

113.                         m.invoke(object, value); 

114.  

115.                     } else if (fieldType.endsWith("short") 

116.                             || fieldType 

117.                                     .endsWith("fieldType:class java.lang.Short")) { 

118.                         // short 

119.                         Method m = object.getClass().getMethod(methodName, 

120.                                 short.class); 

121.                         int value = -1; 

122.                         try { 

123.                             value = response.getInt(fieldName); 

124.                         } catch (Exception e) { 

125.                             e.printStackTrace(); 

126.                             value = -1; 

127.                         } 

128.                         m.invoke(object, value); 

129.                     } else if (fieldType.endsWith("byte") 

130.                             || fieldType 

131.                                     .endsWith("fieldType:class java.lang.Byte")) { 

132.                         Method m = object.getClass().getMethod(methodName, 

133.                                 byte.class); 

134.                         int value = -1; 

135.                         try { 

136.                             value = response.getInt(fieldName); 

137.                         } catch (Exception e) { 

138.                             e.printStackTrace(); 

139.                             value = -1; 

140.                         } 

141.                         m.invoke(object, value); 

142.                     } else if (fieldType.endsWith("long") 

143.                             || fieldType 

144.                                     .endsWith("fieldType:class java.lang.Long")) { 

145.                         Method m = object.getClass().getMethod(methodName, 

146.                                 long.class); 

147.                         Long value = -1L; 

148.                         try { 

149.                             value = response.getLong(fieldName); 

150.                         } catch (Exception e) { 

151.                             e.printStackTrace(); 

152.                             value = -1L; 

153.                         } 

154.                         m.invoke(object, value); 

155.                     }   

156.                 } catch (Exception e) { 

157.                     // TODO: handle exception 

158.                 } 

159.             } 

160.             return (T) object; 

161.         } catch (Exception e) { 

162.             e.printStackTrace(); 

163.         } 

164.  

165.         return null; 

166.     } 

167.  

168. }  

这里需要注意一个坑,先来看一段代码

1. class People { 

2.  

3.     private String name

4.     private int age; 

5.     private String mSex; 

6.  

7.     public String getName() { 

8.         return name

9.     } 

10.  

11.     public void setName(String name) { 

12.         this.name = name

13.     } 

14.  

15.     public int getAge() { 

16.         return age; 

17.     } 

18.  

19.     public void setAge(int age) { 

20.         this.age = age; 

21.     } 

22.  

23.     public String getmSex() { 

24.         return mSex; 

25.     } 

26.     // 这里就出了问题   

27.     public void setmSex(String mSex) { 

28.         this.mSex = mSex; 

29.     } 

30.  

31. }  

当我们自动生成get set方法时,会将字段的首字母大写,我们在上面拼接set 方法时,也是基于这样的规则来拼装的。但是 当我们的字段名为 aAbbb 时,则生成的get set 方法则不会大写。解决方案也很简单,注意字段命名或者在拼接时对第二个自动进行大小写判断。这样我们自己写的Json解析工具就搞定, 以后每次解析只需一行代码即可OK。

 


如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

¥ 打赏支持
454人赞 举报
分享到
用户评价(0)

暂无评价,你也可以发布评价哦:)

扫码APP

扫描使用APP

扫码使用

扫描使用小程序