Java反射机制可以在我们运行时期获取任何一个类的各种信息。如属性,方法等。还能动态调用类中的方法,动态操作运行中类的属性。
不过使用反射最大的弊端是性能比较差,反射的操作会比直接操作慢好多。
基本用法
- 获取Class对象
在使用反射之前要先获取要操作的类对象。
定义了一个类,里面有一个int的属性。
1 |
|
获取MyClass对象
一种是通过已经创建的MyClass对象直接获取
还有一种通过MyClass的完整类名去获取。
当然直接 类名.class 也能够获取1
2
3
4
5
6// 通过已创建的MyClass获取
Class myClass = MyClass.getClass();
// 通过forName获取
Class myClass = Class.forName("util.MyClass");
Class myClass = MyClass.class;获取执行类的属性、方法等
获取:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17// 获取所有属性
Field[] fields = myClass.getFields();
//获取当前类自己定义的属性
Field[] declaredFields = myClass.getDeclaredFields();
// 获取所有方法
Method[] methods = myClass.getMethods();
// 获取本类中自己定义的方法
Method[] declaredmethods = myClass.getMethods();
// 获取继承的父类
Class fatherClass = myClass.getSuperclass();
// 获取实现的接口
Class[] InterfaceClass = myClass.getInterfaces();执行:
1
2
3
4
5
6
7
8
9
10
11
12MyClass myClassObject = new MyClass(1);
Class myClass = myClassObject.getClass();
// 获取setProperty方法
Method setProperty = myClass.getDeclaredMethod("setProperty",int.class);
// 对setProperty方法取消安全检查,如果setProperty方法是private的话,就必须要设置这个才能使用
setProperty.setAccessible(true);
// 执行方法,将property设置成了10,第一个参数是要执行的Object类,第二个参数是方法参数(可以有多个)
setProperty.invoke(myClassObject,10);
Method getProperty = myClass.getDeclaredMethod("getProperty",null);
// 通过执行getProperty看一下有没有通过反射把值设置成功
int result = (int) getProperty.invoke(myClassObject,null);上面就是java反射机制简单介绍。
下面结合我具体做过的案例介绍一下。
具体案例
使用DataTable作为前端图表插件,后端持久层用的MyBatis
因为每次要分页的时候都需要对java实体类进行各种拼装参数的操作,重复的劳动我就索性使用反射把实体类给封装了。
父类:
1
2
3
4
5
6
7
8
9
public class DataTable {
private Integer iDisplayStart; //分页 从数据库 第几条开始
private Integer iDisplayLength; //分页 从数据库中获取多少条
private int iSortCol_0; // 排序列 获取的是列的下标,从0 开始,包括不可排序的列
private String sSortDir_0; // 排序 该列的排序方式desc asc
private String sSearch;
// ...getXX()、setXXX()
}子类
1
2
3
4
5
6
7
public class AccidentList extends DataTable {
private Integer id;
private String orderNo;
private String dept;
private String accident;
// ...getXX()、setXXX()封装:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
public class Pagging {
/**
* 通过反射设置分页信息
*
* @param example
* @param model
* @return
*/
public static Object getPageData(Object example, Object model, String[] params) {
try {
Field setOffset = example.getClass().getDeclaredField("offset");
setOffset.setAccessible(true);
Field setLimit = example.getClass().getDeclaredField("limit");
setLimit.setAccessible(true);
Field setOrderByClause = example.getClass().getDeclaredField("orderByClause");
setOrderByClause.setAccessible(true);
if (((DataTable) model).getiDisplayStart() != null && ((DataTable) model).getiDisplayLength() != null && ((DataTable) model).getsSearch() != null) {
Field getiDisplayStart = model.getClass().getSuperclass().getDeclaredField("iDisplayStart");
getiDisplayStart.setAccessible(true);
Field getiDisplayLength = model.getClass().getSuperclass().getDeclaredField("iDisplayLength");
getiDisplayLength.setAccessible(true);
Field getsSearch = model.getClass().getSuperclass().getDeclaredField("sSearch");
getsSearch.setAccessible(true);
// 设置分页
setOffset.set(example, getiDisplayStart.get(model));
setLimit.set(example, getiDisplayLength.get(model));
// 设置排序
String a = (String) model.getClass().getSuperclass().getDeclaredMethod("getsSortDir_0").invoke(model);
Integer b = (Integer) model.getClass().getSuperclass().getDeclaredMethod("getiSortCol_0").invoke(model);
setOrderByClause.set(example, params[b] + " " + a);
// 设置搜索
for (int i = 0; i < params.length; i++) {
Object criteria = example.getClass().getDeclaredMethod("or").invoke(example);
String p = params[i];
try {
ReflectUtils.invokePrivateMethod(criteria, StringUtil.camelName("and_" + p + "_like"), String.class, "%" + getsSearch.get(model) + "%");
ReflectUtils.invokePrivateMethod(criteria, "andIsShowEqualTo", Integer.class, 1);
} catch (Exception e) {
try {
ReflectUtils.invokePrivateMethod(criteria, StringUtil.camelName("and_" + p + "_equal_to"), Integer.class, Integer.valueOf((String) getsSearch.get(model)));
ReflectUtils.invokePrivateMethod(criteria, "andIsShowEqualTo", Integer.class, 1);
} catch (Exception no) {
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return example;
}
}
public class ReflectUtils {
/**
* 创建类的实例,调用类的无参构造方法
*
* @param className
* @return
*/
public static Object newInstance(String className) {
Object instance = null;
try {
Class<?> clazz = Class.forName(className);
instance = clazz.newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
// if this Class represents an abstract class, an interface, an
// array class, a primitive type, or void; or if the class has no
// nullary constructor; or if the instantiation fails for some other
// reason.
e.printStackTrace();
} catch (IllegalAccessException e) {
// if the class or its nullary constructor is not accessible
e.printStackTrace();
}
return instance;
}
/**
* 获取所有的public构造方法的信息
*
* @param className
* @return
*/
public static String getPublicConstructorInfo(String className) {
StringBuilder sBuilder = new StringBuilder();
try {
Class<?> clazz = Class.forName(className);
Constructor<?>[] constructors = clazz.getConstructors();
sBuilder.append(getConstructorInfo(constructors));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return sBuilder.toString();
}
/**
* 得到本类内声明的构造方法信息
*
* @param className
* @return
*/
public static String getDeclearedConstructorInfo(String className) {
StringBuilder sBuilder = new StringBuilder();
try {
Class<?> clazz = Class.forName(className);
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
sBuilder.append(getConstructorInfo(constructors));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return sBuilder.toString();
}
/**
* 获取public的字段信息
*
* @param className
* @return
*/
public static String getPublicFieldInfo(String className) {
StringBuilder sBuilder = new StringBuilder();
try {
Class<?> clazz = Class.forName(className);
Field[] fields = clazz.getFields();
sBuilder.append(getFieldInfo(fields));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return sBuilder.toString();
}
/**
* 获取本类内声明的字段信息
*
* @param className
* @return
*/
public static String getDecleardFieldInfo(String className) {
StringBuilder sBuilder = new StringBuilder();
try {
Class<?> clazz = Class.forName(className);
Field[] fields = clazz.getDeclaredFields();
sBuilder.append(getFieldInfo(fields));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return sBuilder.toString();
}
/**
* 得到所有public方法信息
*
* @param className
* @return
*/
public static String getPublicMethodInfos(String className) {
StringBuilder sBuilder = new StringBuilder();
try {
Class<?> clazz = Class.forName(className);
Method[] methods = clazz.getMethods();// 得到所有的public方法,包括从基类继承的
sBuilder.append(getMethodInfo(methods));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return sBuilder.toString();
}
/**
* 得到类内声明的方法信息
*
* @param className
* @return
*/
public static String getDeclaredMethodInfos(String className) {
StringBuilder sBuilder = new StringBuilder();
try {
Class<?> clazz = Class.forName(className);
Method[] methods = clazz.getDeclaredMethods();// 得到本类声明的所有方法,包括私有方法
// clazz.getMethods(); 会返回所有public的方法,但是包括基类Object的方法
sBuilder.append(getMethodInfo(methods));
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return sBuilder.toString();
}
/**
* 得到构造器信息
*
* @param constructor
* @return
*/
private static String getConstructorInfo(Constructor<?> constructor) {
StringBuilder sBuilder = new StringBuilder();
sBuilder.append("name: " + constructor.getName());
sBuilder.append("\ngetParameterTypes: "
+ Arrays.toString(constructor.getParameterTypes()));
return sBuilder.toString();
}
/**
* 将一组构造器的信息组成一个字符串返回
*
* @param constructors
* @return
*/
private static String getConstructorInfo(Constructor<?>[] constructors) {
StringBuilder sBuilder = new StringBuilder();
int i = 0;
for (Constructor<?> c : constructors) {
sBuilder.append("method: " + ++i + " : ");
sBuilder.append("\n" + getConstructorInfo(c));
sBuilder.append("\n");
}
return sBuilder.toString();
}
/**
* 获取字段信息,组成一个字符串返回
*
* @param field
* @return
*/
private static String getFieldInfo(Field field) {
StringBuilder sBuilder = new StringBuilder();
sBuilder.append("name: " + field.getName());
sBuilder.append("\ngetType: " + field.getType());
sBuilder.append(getModifiersInfo(field));
return sBuilder.toString();
}
/**
* 获取一组字段的信息,返回字符串
*
* @param fields
* @return
*/
private static String getFieldInfo(Field[] fields) {
StringBuilder sBuilder = new StringBuilder();
int i = 0;
for (Field field : fields) {
sBuilder.append("field: " + ++i + " : ");
sBuilder.append("\n" + getFieldInfo(field));
sBuilder.append("\n");
}
return sBuilder.toString();
}
/**
* 获取方法的信息,组成一个字符串返回
*
* @param method
* @return
*/
private static String getMethodInfo(Method method) {
StringBuilder sBuilder = new StringBuilder();
sBuilder.append("name: " + method.getName());
sBuilder.append("\ngetReturnType: " + method.getReturnType());
sBuilder.append("\ngetParameterTypes: "
+ Arrays.toString(method.getParameterTypes()));
sBuilder.append(getModifiersInfo(method));
return sBuilder.toString();
}
/**
* 获取一组方法的信息,组成一个字符串返回
*
* @param methods
* @return
*/
private static String getMethodInfo(Method[] methods) {
StringBuilder sBuilder = new StringBuilder();
int i = 0;
for (Method method : methods) {
sBuilder.append("method: " + ++i + " : ");
sBuilder.append("\n" + getMethodInfo(method));
sBuilder.append("\n");
}
return sBuilder.toString();
}
/**
* 获取修饰符信息
*
* @param member
* @return
*/
private static String getModifiersInfo(Member member) {
StringBuilder sBuilder = new StringBuilder();
int modifiers = member.getModifiers();
sBuilder.append("\ngetModifiers: " + +modifiers + ", ");// 得到修饰符编码
sBuilder.append("\nisPublic: " + Modifier.isPublic(modifiers) + ", ");
sBuilder.append("\nisPrivate: " + Modifier.isPrivate(modifiers) + ", ");
sBuilder.append("\nisStatic: " + Modifier.isStatic(modifiers) + ", ");
sBuilder.append("\nisFinal: " + Modifier.isFinal(modifiers) + ", ");
sBuilder.append("\nisAbstract: " + Modifier.isAbstract(modifiers));
return sBuilder.toString();
}
/**
* 是否是公用静态方法
*
* @param member
* @return
*/
private static boolean isPublicStatic(Member member) {
boolean isPS = false;
int mod = member.getModifiers();
isPS = Modifier.isPublic(mod) && Modifier.isStatic(mod);
return isPS;
}
/**
* 调用静态方法
*
* @param className
* @param methodName
* @param paramTypes
* @param params
* @return
* @throws Exception
*/
public static Object invokePublicStaticMethod(String className,
String methodName, Class<?>[] paramTypes, Object[] params)
throws Exception {
Class<?> cls = Class.forName(className);
Method method = cls.getMethod(methodName, paramTypes);
Object value = null;
if (isPublicStatic(method)) {
value = method.invoke(null, params);
}
return value;
}
/**
* 调用私有方法
*
* @param obj 调用类对象
* @param methodName 方法名
* @param paramTypes 参数类型
* @param params 参数
* @return
* @throws Exception
*/
public static Object invokePrivateMethod(Object obj, String methodName,
Class<?> paramTypes, Object params) throws Exception {
Object value = null;
Class<?> cls = obj.getClass();
// 注意不要用getMethod(),因为getMethod()返回的都是public方法
Method method = cls.getDeclaredMethod(methodName, paramTypes);
method.setAccessible(true);// 抑制Java的访问控制检查
value = method.invoke(obj, params);
return value;
}
}使用的时候只需要:
1
2
3
4
5
6
7
8
// 定义好排序的字段
private static final String[] Params = {"id", "order_no", "dept", "accident","occur_date","occur_mouth","accident_type","name","age","sex","into_date","workday_loss","direct_loss","com_flag","injury_flag","rectifica_measure","handle","bullentin_attachment","report_attachment","sub_person","sub_date","us_status","update_date"};
public List<AccidentList> getAllFileInfo(AccidentList list) {
AccidentListExample accidentListExample = (AccidentListExample) Pagging.getPageData(new AccidentListExample(), list, Params);
return accidentListMapper.selectByExample(accidentListExample);
}