目录
- 获取字段和赋值字段
- 获取方法
- 获取构造方法
- 获取继承关系
- 动态代理
- 反射util
反射,在java中是非常常见的一功能和操作。
我最常听到的就是,xx框架在什么什么的时候采用的反射,从而达到动态代理的效果等等。然后就什么什么框架因为包含反射所以不安全或者速度不够快等等。
道听途说总是迷茫和羡慕,待我认真看起反射以后,发现也没有想象中的那么难,但却十分的酷炫。
获取字段和赋值字段
首先,简单的反射使用,获取字段和赋值字段是我最经常使用的,可以简单的写个通用方法,非常便捷
public static void setValue(Object object, String key, Object value){
try {
Class clazz = object.getClass();
Field field = clazz.getDeclaredField(key);
field.setAccessible(true);
field.set(object, value);
}catch (Exception e){
System.out.println(e);
}
}
public static Object getValue(Object object, String key){
try {
//如果想专门找父类可以用getClass().getSuperclass()
Class clazz = object.getClass();
//获取非public得用getDeclaredField,getField可以获取到父类的
Field field = clazz.getDeclaredField(key);
//此设置重要,大多数字段封装都是私有的,设置以后才能访问非public字段
field.setAccessible(true);
Object value = field.get(object);
return value;
}catch (Exception e){
System.out.println(e);
}
return null;
}
获取方法
用的少就直接复制了,感觉获取方法并不好做通用工具,又要区分多态,还要确认形参个数和类型然后还有返回值类型,感觉如果都知道了,暂时还没想到怎么写工具类,等我再看看
//其实用起来在获取上和字段差距不大
//第一个参数是方法名,后面可以填多个是代表形参类型
Method m = getClass().getMethod("方法名",int.class...);
//非public方法用Class.getDeclaredMethod()
//Method也有setAccessible方法和Field的作用基本一样
m.setAccessible(true);
//对于Method,使用invoke方法就相当于调用Method
//如果是静态方法,invoke第一参数为null
//如果是非静态方法,invoke第一参数应为对象实体,很好理解,只有静态方法才能脱离实体。
m.invoke(object,1);
获取构造方法
Constructor对象和Method非常类似,不同之处仅在于它是一个构造方法,并且,调用结果总是返回实例
// 获取非public的用getDeclaredConstructor
// 获取构造方法Integer(int):
Constructor cons1 = Integer.class.getConstructor(int.class);
// 调用构造方法:
Integer n1 = (Integer) cons1.newInstance(123);
System.out.println(n1);
// 获取构造方法Integer(String)
Constructor cons2 = Integer.class.getConstructor(String.class);
Integer n2 = (Integer) cons2.newInstance("456");
System.out.println(n2);
复制了一下廖雪峰老师的代码,说实话,获取构造方法的使用,比获取方法和字段都更简单。因为构造方法与父类无关,且大多都是public,setAccessible方法甚至大多可以不写。
不过使用场景很难想象,这也是我直接复制的愿意,等我找到合适的使用场景再回来更新。
获取继承关系
// 获取类
getClass()
// 获取父类
getSuperclass()
//获取类实现的接口(注:返回的是个Class[]数组)
getInterfaces()
这个其实大家应该都知道,不过用的地方也不多就是了。
动态代理
没看懂,等我看两天着
最近换了公司,比较摆,也很迷茫,最近算是收拾收拾准备好好学习,虽然不知道前方是什么在等待着我,但学习总是没错的,共勉
反射util
public class MyReflectUtils {
/**
* 利用递归找一个类的指定方法,如果找不到,去父亲里面找直到最上层Object对象为止。
*
* @param clazz
* 目标类
* @param methodName
* 方法名
* @param classes
* 方法参数类型数组
* @return 方法对象
* @throws Exception
*/
public static Method getMethod(Class clazz, String methodName,
final Class[] classes) throws Exception {
Method method = null;
try {
method = clazz.getDeclaredMethod(methodName, classes);
} catch (NoSuchMethodException e) {
try {
method = clazz.getMethod(methodName, classes);
} catch (NoSuchMethodException ex) {
if (clazz.getSuperclass() == null) {
return method;
} else {
method = getMethod(clazz.getSuperclass(), methodName,
classes);
}
}
}
return method;
}
/**
*
* @param obj
* 调整方法的对象
* @param methodName
* 方法名
* @param classes
* 参数类型数组
* @param objects
* 参数数组
* @return 方法的返回值
*/
public static Object invoke(final Object obj, final String methodName,
final Class[] classes, final Object[] objects) {
try {
Method method = getMethod(obj.getClass(), methodName, classes);
method.setAccessible(true);// 调用private方法的关键一句话
return method.invoke(obj, objects);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static Object invoke(final Object obj, final String methodName,
final Class[] classes) {
return invoke(obj, methodName, classes, new Object[] {});
}
public static Object invoke(final Object obj, final String methodName) {
return invoke(obj, methodName, new Class[] {}, new Object[] {});
}
/**
* 返回当前对象父类的属性值
* @param object 当前对象
* @param key 属性名
* @return 属性值
*/
public static Object getSuperValue(Object object, String key){
try {
//如果想专门找父类可以用getClass().getSuperclass()
Class clazz = object.getClass().getSuperclass();
//获取非public得用getDeclaredField,getField可以获取到父类的
Field field = clazz.getDeclaredField(key);
//此设置重要,大多数字段封装都是私有的,设置以后才能访问非public字段
field.setAccessible(true);
Object value = field.get(object);
return value;
}catch (Exception e){
System.out.println(e);
}
return null;
}
/**
* 获取当前对象的属性值
* @param object 当前对象
* @param key 属性名
* @return 属性值
*/
public static Object getValue(Object object, String key){
try {
//如果想专门找父类可以用getClass().getSuperclass()
Class clazz = object.getClass();
//获取非public得用getDeclaredField,getField可以获取到父类的
Field field = clazz.getDeclaredField(key);
//此设置重要,大多数字段封装都是私有的,设置以后才能访问非public字段
field.setAccessible(true);
Object value = field.get(object);
return value;
}catch (Exception e){
System.out.println(e);
}
return null;
}
}