java反射获取方法以及调用方法

Java反射获取方法以及调用方法

获取方法

1.先找到方法所在类的字节码

2.找到需要被获取的方法

Class类中获取方法:

public Method[] getMethods();//获取包括自身和继承(实现)过来的所有的public方法——Method不支持泛型<>,即后面不接<>

public Method[] getDeclaredMethods();//获取自身所有的方法(privatepublicprotected和访问权限无关)不包括继承的

public Method[] getMethod(String methodName, Class<T>...parameterTypes);//表示获取指定的一个公共的方法,包括继承的

参数: methodName:表示获取的方法的名字

           parameterTypes:表示获取的方法的参数的Class类型

public Method[] getDeclaredMethod(String methodName, Class<T>...parameterTypes);//表示获取本类中的一个指定的方法(privateprotectedpublic与访问权限无关),不包括继承的方法

 

通过反射调用方法:

1.先找到方法所在类的字节码

2.找到需要被获取的方法

3.调用该方法

class User{

                    public void sayHello(){...}

                    public void sayHi(String naem){...}

                    private  void sayGoodBye(String name, int age){...}

}

 

如何使用反射调用一个方法?

Method类中有一个方法:

public Object invoke(Object  obj,  Object...  args);//表示调用当前Method所表示的方法

     参数:  obj: 表示被调用方法底层所属对象

                 args: 表示调用方法时传递的实际参数

     返回:方法调用后,底层方法的返回结果

Eg:   public  String  sayYaString name{....}

Class<User> clz=User.class;

Method mt=clz.getMethod(“sayYa”, String.class);

Object obj=clz.newInstance();

Object ret=mt.invoke(obj, “wili”);//要调用实例方法,必须有一个对象,方法的底层对象就是指当前Method所在的类的实例对象,sayHi方法具有返回值,调用该方法后的返回结果使用Object接收

 

调用私有方法:

Method mt=clz.getDeclaredMethod(“sayGoodBye”, String.class, int.class);

在调用私有方法之前,需设置该方法为可访问的权限:——否则会报错

mt.setAccessible(true);

mt.invoke(clz.newInstance(), “limi”, 17);

 

调用静态方法

class User{

            public static void staticMethod(){

                       System.out.println(“static mthod invoke.”);

            }

}

Eg:

Class<User> clz=User.class;

Method staticMethod=clz.getMethod(“staticMthod”);

两种方式调用静态方法:

1. 因为静态方法属于所有实例对象公共的,可以创建该类的一个任意对象,通过该对象调用

 staticMethod.invoke(clz.newInstance());//staticMethod无参,故参数列表类型不填

2. 如果底层方法是静态的,那么可以忽略指定的obj参数,将obj参数设置为null即可

staticMethod.invoke(null);

 

 

使用反射调用可变参数的方法

class User{

public static int  sum(int... ages){

           System.out.println(args);//打印结果可看出:可变参数底层就是一个数组

           Int sum=0;

           for(int i : args){

                  Sum+=i;

           }

            return sum;

}

            public static void show(String... args){...}

}

Eg:

Class<User> clz=User.class;

Method m=clz.getMethod(“sum”, int[].class);//可变参数底层就是一个数组

M.invoke(null,  new int[]{1,2,3});

Method m=clz.getMethod(“show”, String[].class);

M.invoke(null,  new String[]{A,B,C});//会报错,可变参数是引用类型时,底层会自动解包,上述调用被解包后变成M.invoke(null,A,B,C);——为了解决该问题,我们再使用一层数组把实际参数包装起来

M.invoke(null,  new Object[]{new String[]{A,B,C}});//正确

 

通用方法:

以后在使用反射调用invoke方法时,在传递实际参数的时候,无论是基本数据类型,还是引用类型,或者是可变参数类型,把实际参数都包装在一维数组中。

m.invoke(方法的底层对象,new Object[]{实际参数})

Eg

m.invoke(null, new Object[]{17});//方法参数为基本类型,且只有一个参数,解包后变成m.invoke(null17});

m.invoke(null, new Object[]{xxx});//方法参数为String类型,且只有一个参数

m.invoke(null, new Object[]{new int[]{1,2}});//方法参数为int类型,且为可变参数或者数组类型

m.invoke(null, new Object[]{new String[]{A,B}});//方法参数为String类型,且为可变参数或者数组类型,new String[]{A,B}为传递的实际参数



示例:

1.用户类

package com.lf.entity;

import com.lf.annotation.SetProperty;
import com.lf.annotation.SetTable;

public class UserEntity {
    private String userName;
    private int userAge;
    
    private final int money = 10000;
    
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public int getUserAge() {
        return userAge;
    }
    public void setUserAge(int userAge) {
        this.userAge = userAge;
    }
    //借钱方法
    public int getMoney(){
        System.out.println("你借了 " + money + "元!");
        return money;
    }
    //还钱方法,单个参数
    public void repay(int money){
        System.out.println("你还了 " + money + "元!");
    }
    //还钱方法,多个参数
    public void repay(String userName,int money){
        System.out.println(userName+ " 还了 " + money + "元!");
    }
}

2.测试类

package com.lf.test;

import java.lang.reflect.Method;

import com.lf.entity.UserEntity;

public class Reflection {


    //反射调用方法获取返回值
    //第一种方法,获取对象,直接通过对象调用方法
    //第二种方法,通过方法名获取方法,执行方法
    public static void main(String[] args) throws Exception {
        Class<?> userClass = Class.forName("com.lf.entity.UserEntity");
        UserEntity userEntity = (UserEntity) userClass.newInstance();

        //第一种方法
        System.out.println("第一次借钱:");
        int money = userEntity.getMoney();
        System.out.println("实际拿到钱为: " + money);
        System.out.println("------------------------分割线------------------------");

        //第二种方法,(无参的示例:借钱)
        System.out.println("第二次借钱:");
        Method getMoney = userClass.getMethod("getMoney");//得到方法对象
        Object money2 = getMoney.invoke(userEntity);//调用借钱方法,得到返回值
        System.out.println("实际拿到钱为:" + money2);
        System.out.println("------------------------分割线------------------------");

        //第二种方法,(单个参数的示例:还钱)
        System.out.println("第一次还钱:");
        Method repay1 = userClass.getMethod("repay",int.class);//得到方法对象,有参的方法需要指定参数类型
        repay1.invoke(userEntity,3000);//执行还钱方法,有参传参
        System.out.println("------------------------分割线------------------------");

        //第二种方法,(单个参数的示例:还钱)
        System.out.println("第二次还钱:");
        Method repay2 = userClass.getMethod("repay", String.class,int.class);//得到方法对象,有参的方法需要指定参数类型
        repay2.invoke(userEntity,"小飞",5000);//执行还钱方法,有参传参


    }
}


原文:http://blog.csdn.net/u014207606/article/details/53386043

https://www.cnblogs.com/leifei/p/8252979.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值