目录

  • 获取字段和赋值字段
  • 获取方法
  • 获取构造方法
  • 获取继承关系
  • 动态代理
  • 反射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;
    }
}