Java反射大发
俗话说的好:“无反射,无框架!”
最近由于频繁的对客户端打patch,无时无刻不用到反射,竟然发现原来写的反射工具类有bug。
总结一下使用反射的常见使用,本人语言组织能力极差,以下尽可能用代码说话
工具类源码下载地址:https://github.com/JeffWangGithub/ReflectUtil
————关于反射调用方法————–
获取方法Method对象
- Class.getMethod()此方法只能获取到public的方法
Class.getDeclaredMethod()此方法可以获取到所有的方法,没有修饰符的影响
注意:从效率上讲,getDeclaredMethod()方法的效率是比getMethod()低的,因此如果知道需要获取的Method的修饰符,最好选择效率高的方法。
通用的方法:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21/**
* 获取某个类声明的Method对象,会依次寻找当前类和其父类,找到则返回
*/
public static Method getDeclaredMethod(Class<?> clazz, String methodName,
Class<?>... parameterTypes) {
if(clazz != null){
//从当前类开始寻找,依次想其父类开始寻找,知道找到为止
for (; Object.class != clazz; clazz = clazz.getSuperclass()){
try {
Method declaredMethod = clazz.getDeclaredMethod(methodName, parameterTypes);
if(declaredMethod != null){
declaredMethod.setAccessible(true);
return declaredMethod;
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
return null;
}
获取某个类的父类的方法Mehod对象:不需要过多解释了吧,看懂上面的你肯定就会这个了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21/**
* 获取父类的方法
*/
public static Method getSuperMethod(Class<?> currentClazz, String methodName, Class<?>... parameterTypes){
if(currentClazz != null && currentClazz.getSuperclass() != Object.class){
for(currentClazz = currentClazz.getSuperclass(); Object.class != currentClazz ; currentClazz = currentClazz.getSuperclass()){
try {
Method declaredMethod = currentClazz.getDeclaredMethod(methodName, parameterTypes);
if(declaredMethod != null){
declaredMethod.setAccessible(true);
return declaredMethod;
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
return null;
}调用super方法,即调用父类的方法
1
2
3
4
5
6
7
8
9
10
11
12
13/**
* 调用当前对象父类的方法,即super方法
*/
public static Object invokeSuperMethod(Object currentObject, String methodName, Class<?>... parameterTypes) throws Exception {
if(currentObject != null){
Method superMethod = getSuperMethod(currentObject.getClass(), methodName, parameterTypes);
if(superMethod != null){
superMethod.setAccessible(true);
return superMethod.invoke(currentObject, parameterTypes);
}
}
throw new Exception("invoke method fail");
}调用方法
1
2
3
4
5
6
7
8
9
10
11
12/**
*调用当前对象的方法,可用于静态和非静态方法
*/
public static Object invokeMethod(Object object, String methodName,
Class<?>[] parameterTypes, Object[] paramValues) throws Exception {
Method method = getDeclaredMethod(object.getClass(), methodName,
parameterTypes);
if (method != null) {
return method.invoke(object, paramValues);
}
throw new Exception("invoke method fail");
}调用静态方法(private、public或protected)
调用时直接使用invoke(null, parameterTypes)即可,当然此处使用一个对象也没有问题, API的解释为If the underlying method is static, then the specified obj argument is ignored. It may be null.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15/**
* 调用静态方法
*/
public static Object invokeStaticMethod(Object object, String methodName,
Class<?>[] parameterTypes, Object[] paramValues) throws Exception {
if(object != null){
Method method = getDeclaredMethod(object.getClass(), methodName,
parameterTypes);
if (method != null) {
method.setAccessible(true);
return method.invoke(null, paramValues);
}
}
throw new Exception("invoke method fail");
}
——————关于字段———————-
获取字段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23private static Field getDeclaredField(Class<?> clazz, String fieldName) {
if (clazz != null) {
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append(clazz.getName());
stringBuffer.append(fieldName);
String key = stringBuffer.toString();
if (fieldCache.containsKey(key)) {
return fieldCache.get(key);
} else {
Field field = null;
for (; clazz != Object.class; clazz = clazz.getSuperclass()) {
try {
field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
fieldCache.put(key, field);
return field;
} catch (Exception e) {
}
}
}
}
return null;
}获取某个对象的某个字段的值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17/**
* 根据Object对象获取Object中的fieldValue,一般用作获取非静态字段
* @param object
* @param fieldName
* @return
* @throws Exception
*/
public static Object getFieldValue(Object object, String fieldName)
throws Exception {
Field field = getDeclaredField(object.getClass(), fieldName);
if (field != null) {
return field.get(object);
} else {
throw new Exception("getFieldValue fail");
}
}给某个对象的某个字段设置value
public static void setFieldValue(Class<?> clazz, String fieldName, Object value) throws Exception { Field field = getDeclaredField(clazz, fieldName); if (field != null) { field.set(null, value); } else { throw new Exception(fieldName+" fail"); } }