Java基础--反射之Method

一、反射

Reflection(反射)是Java被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的內部信息,并能直接操作任意对象的内部属性及方法。

Java反射机制主要提供了以下功能:

  • 在运行时构造任意一个类的对象
  • 在运行时获取任意一个类所具有的成员变量和方法
  • 在运行时调用任意一个对象的方法(属性)
  • 生成动态代理

二、Method基础

    /**
     * Class 是对一个类的描述
     * 类的属性: Field
     * 类的方法: Method
     * 类的构造器: Constructor
     *
     * Method: 对应类中的方法
     * 1.获取Method
     * 1.1 获取类的方法数组:getDeclaredMethods()
     * 1.2 获取指定的方法:
     * public Method getDeclaredMethod(String name,
     *                                 Class<?>... parameterTypes)
     *     name - the name of the method
     *     parameterTypes - the parameter array
     *
     * 1.3 用过 Method对象执行方法
     * public Object invoke(Object obj,
     *                      Object... args)
     *     obj  - the object the underlying method is invoked from
     *     args - the arguments used for the method call
     *
     */
    @Test
    public void test4() throws Exception{
        String className = "com.wang.reflection.Person";
        Class clazz = Class.forName(className);

        //1. 得到clazz对应类中的方法,不能获取私有方法
        Method[] methods = clazz.getMethods();
        for(Method method : methods) {
            System.out.println("1." + method);
        }

        System.out.println();

        //2.获取所有方法,包括私有,且只获取当前类声明的方法
        Method[] methods2 = clazz.getDeclaredMethods();
        for(Method method : methods2) {
            System.out.println("2." + method);
        }

        System.out.println();

        //3.获取指定的方法
        Method method = clazz.getDeclaredMethod("test");
        System.out.println("3." + method);

        method = clazz.getDeclaredMethod("setName", String.class);
        System.out.println("3." + method);

        System.out.println();

        //4.执行方法
        System.out.println("4.");
        Object obj = clazz.newInstance();
        method.invoke(obj,"wang");
    }

执行结果:

写一个方法:

    /**
     * 通过一个类的全类名、方法名和参数来执行该方法
     *
     * @param className  某个类的全类名
     * @param methodName 类的一个方法名
     * @param args       需要的参数
     * @return           方法的返回值
     */
    public Object invoke(String className, String methodName, Object ... args) {
        try {
            Object obj = Class.forName(className).newInstance();
            return invoke(obj, methodName, args);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 通过一个方法的对象、名称、参数来执行该方法
     *
     * @param obj        要执行的方法的对象
     * @param methodName 要执行的方法名
     * @param args       要执行方法的参数
     * @return           方法的返回值
     */
    public Object invoke(Object obj, String methodName, Object ... args) {
        //1. 获取Method对象
        Class [] parameterTypes = new Class[args.length];
        for(int i = 0; i < args.length; ++i) {
            parameterTypes[i] = args[i].getClass();
        }
        try {
            Method method = obj.getClass().getMethod(methodName, parameterTypes);
            //2.执行Method方法,并返回值
            return method.invoke(obj,args);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Test
    public void test5() {
        Object result =
                invoke("java.text.SimpleDateFormat", "format", new Date());
        System.out.println(result);
    }

执行结果:

三、获取并执行父类的私有方法

(1)获取父类的私有方法

    /**
     * 获取当前类的父类
     * 直接调用 Class对象的 getSuperclass()方法
     */
    @Test
    public void test6() throws Exception {
        String className = "com.wang.reflection.Student";
        Class clazz = Class.forName(className);
        Class superClazz = clazz.getSuperclass();
        System.out.println(superClazz);
    }

(2)invoke() 调用私有方法

    /**
     * 若通过 Method的 invoke()调用私有方法,需要执行:
     * method.setAccessible(true);
     *
     */
    @Test
    public void test7() throws Exception {
        Object obj = new Student();
        Class clazz = obj.getClass();
        Method method = clazz.getDeclaredMethod("method1", Integer.class);
        System.out.println(method);

        //若要通过反射执行私有方法
        method.setAccessible(true);
        method.invoke(obj, 10);
    }

(3)获取当前类或父类中的方法

    /**
     * 获取 clazz的 methodName方法,该方法可能是私有方法,也可能是父类中的(私有方法)
     * @param clazz          clazz
     * @param methodName     方法名称
     * @param parameterTypes 方法参数
     * @return               Method
     */
    public Method getMethod(Class clazz, String methodName, Class ... parameterTypes) {
        for(; clazz != Object.class; clazz = clazz.getSuperclass()) {
            try {
                Method method = clazz.getDeclaredMethod(methodName, parameterTypes);
                return method;
            } catch (Exception e) { }
        }
        return null;
    }

    @Test
    public void test8() {
        try {
            Class clazz = Class.forName("com.wang.reflection.Student");
            Method method = getMethod(clazz, "method1", Integer.class);
            System.out.println("method");

            method = getMethod(clazz,"method2");
            System.out.println(method);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

四、执行一个方法

执行一个方法,只要提供类的全类名,方法名和参数,就可执行一个方法,不管是共有方法还是私有方法,不管是在当前类中环是在父类中。

修改之前的invoke方法:

    /**
     * 通过一个类的全类名、方法名和参数来执行该方法
     * 不管这个方法是共有方法还是私有方法,不管在当前类中还是父类中。
     *
     * @param className  某个类的全类名
     * @param methodName 类的一个方法名
     * @param args       需要的参数
     * @return           方法的返回值
     */
    public Object invoke(String className, String methodName, Object ... args) {
        try {
            Object obj = Class.forName(className).newInstance();
            return invoke(obj, methodName, args);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 通过一个方法的对象、名称、参数来执行该方法
     *
     * @param obj        要执行的方法的对象
     * @param methodName 要执行的方法名
     * @param args       要执行方法的参数
     * @return           方法的返回值
     */
    public Object invoke(Object obj, String methodName, Object ... args) {
        //1. 获取Method对象
        Class [] parameterTypes = new Class[args.length];
        for(int i = 0; i < args.length; ++i) {
            parameterTypes[i] = args[i].getClass();
        }
        try {
            //修改1:getMethod方法可以获得当前类或者父类的任何方法
            Method method = getMethod(obj.getClass(), methodName, parameterTypes);
            //2.设置可以执行私有方法
            //修改2:共有、私有方法都可以执行
            method.setAccessible(true);
            //3.执行Method方法,并返回值
            return method.invoke(obj,args);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Test
    public void test9() throws Exception {

        invoke("com.wang.reflection.Student", "method1", 18);

        Object obj = invoke("com.wang.reflection.Student", "method2");
        System.out.print(obj);
    }

 

 

1. Java基础--反射之Class类    http://my.oschina.net/daowuming/blog/703293

2. Java基础--反射之Method    ----当前----

3. Java基础--反射之Field        http://my.oschina.net/daowuming/blog/703605

 

转载于:https://my.oschina.net/daowuming/blog/703567

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值