Java 反射方法的运用(反射调用某个类的方法)

上一篇讲了 通过反射创建对象,这一篇说说 通过反射调用一个类的方法

如果看过了上一篇文章,那么这一篇就很好理解了

如同上一篇文章一样,主要的方法基本上都是通过 Class 这个类(是个入口)

1.得到方法 对象(Method)

public Method getDeclaredMethod(String name,Class<?>... parameterTypes)throws NoSuchMethodException,SecurityException

返回一个 Method 的对象,该对象反映的是 这个Class的类对象所表示的 类或接口 中已经声明的 方法
其中参数 name 是声明的方法名称,parameterTypes 参数是  Class类对象  的一个数组,顺序和这个方法中  参数对应的类  一致
如果在某个类中声明了带有相同参数类型的多个方法,并且其中有一个方法的返回类型比其他方法的返回类型都特殊,则返回该方法;否则将从中任选一个方法。如果名称是 "<init>” 或 “<clinit>",则引发一个 NoSuchMethodException。

参数:
   name - 方法名
   parameterTypes - 参数数组
返回:
   该Class类 与指定名和参数相匹配的方法的 Method 对象
抛出:
   NoSuchMethodException - 如果找不到匹配的方法。
   NullPointerException - 如果 namenull
   SecurityException - 如果存在安全管理器 s,并满足下列任一条件:
   调用 s.checkMemberAccess(this, Member.DECLARED) 拒绝访问已声明方法
   调用者的类加载器不同于也不是当前类的类加载器的一个祖先,并且对 s.checkPackageAccess() 的调用拒绝访问该类的包

得到method 的对象后,进一步调用相应的方法;

2.通过 invoke 调用 声明的方法

public Object invoke(Object obj, Object... args)   

对带有 指定参数 的 指定对象 调用由此 Method 对象表示的底层方法。
其中参数 obj:是调用的具体对象(该对象含有 改声明的方法);args 对应Class数组的类的 具体值(obj对象中声明方法 的参数具体值)

个别参数被自动解包,以便与基本形参相匹配,基本参数和引用参数都随需服从方法调用转换。

如果底层方法是静态的,那么可以忽略指定的 obj 参数。该参数可以为 null。

如果底层方法所需的形参数为 0,则所提供的 args 数组长度可以为 0 或 null。

如果底层方法是实例方法,则使用动态方法查找来调用它,这一点记录在 Java Language Specification, Second Edition 的第 15.12.4.4 节中;在发生基于目标对象的运行时类型的重写时更应该这样做。

如果底层方法是静态的,并且尚未初始化声明此方法的类,则会将其初始化。

如果方法正常完成,则将该方法返回的值返回给调用者;如果该值为基本类型,则首先适当地将其包装在对象中。但是,如果该值的类型为一组基本类型,则数组元素不 被包装在对象中;换句话说,将返回基本类型的数组。如果底层方法返回类型为 void,则该调用返回 null。 

参数:
 obj:从中调用底层方法的对象(包含 声明方法 的具体的对象)
 args:声明方法中参数的 具体值(上一个方法中Class数组 对应类的 具体值)

下面是以上总结的一个实例:
1.首先创建 含有 声明方法的 类:

class DeclareMethod {
    public DeclareMethod(){}

    public void show(){
        System.out.println("我是动态创建的show 方法");
    }

    public void show(Integer temp){
        System.out.println("我是一个参数的 show 方法");
    }

    public void show(Integer a,String name,NewClass nc){
        System.out.println("Integer="+a+" name="+name+" NewClass="+nc);
    }
}

2.创建 自定义的 类(参数不仅仅是基本类型,还有自定义类型)

class NewClass{
    public void print(){
        System.out.println("我是NewClass()");
    }
    @Override
    public String toString(){
        return "NewClass 的 toString 的方法";
    }
}

3.入口类

public class ClassMethod {

    public static void main(String[] args) {
        DeclareMethod m=new DeclareMethod();
//        getMethod("show",m,null);//这个方法可以根据一个字符串来动态创建某个类的相应方法,这个思路非常好。
//        getMethod("show",m,new Object[]{20});

        //包括自定义类 
        getMethod("show",m,new Object[]{100,"今天天气不错",new NewClass()});
    }


    /**
     * @param methodName  方法名称
     * @param obj           调用此方法的对象
     * @param args       调用的这个方法的参数参数列表
     */
    public static void  getMethod(String methodName,Object obj,Object []args){
         Class c[]=null;

        //1.参数存在
         if(args!=null){
             int len=args.length;
             c=new Class[len];

             //2.根据参数得到相应的 Class的类对象
             for(int i=0;i<len;++i){
                 c[i]=args[i].getClass();
             }
         }
        try {

             //3.根据方法名,参数Class类对象数组,得到Method
            Method method=obj.getClass().getDeclaredMethod(methodName,c);
            try {

                //4.通过方法所在的类,和具体的参数值,调用相应的方法
                method.invoke(obj,args);//调用o对象的方法
            } catch (IllegalAccessException ex) {
                Logger.getLogger(ClassMethod.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IllegalArgumentException ex) {
                Logger.getLogger(ClassMethod.class.getName()).log(Level.SEVERE, null, ex);
            } catch (InvocationTargetException ex) {
                Logger.getLogger(ClassMethod.class.getName()).log(Level.SEVERE, null, ex);
            }
        } catch (NoSuchMethodException ex) {
            Logger.getLogger(ClassMethod.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SecurityException ex) {
            Logger.getLogger(ClassMethod.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

参考:直到完成 无形的天空——-Java反射调用某个类的方法(带参数和不带参数)

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值