java反射传参时int被装箱Integer的解决办法

java在将int类型的数据传递给Object的对象时会自动装箱为Integer对象,从而在获取数据的class对象时获取的是Integer.class,而不是int.class==Integer.TYPE。

java反射传参时int被装箱Integer实例

package reflect;

import java.lang.reflect.Method;

public class TInvoke {
     /** 
     * 获取clazz 的methodName 方法, 该方法可能是私有方法 
     */  
    public Method getMethod(Class clazz, String methodName, Class ... parameterTypes) {  
        //注意这个循环里的内容!!! 
        for (; clazz != Object.class; clazz = clazz.getSuperclass()){  
            try {  
                return clazz.getDeclaredMethod(methodName, parameterTypes);  
            } catch (Exception e) { 
                e.printStackTrace();
            }  
        }  
        return null;  
    }  
   /** 
     * @param className  某个类的全类名 
     * @param methodName 类的一个方法的方法名,该方法也可能是私有方法 
     * @param args  调用该方法需要传入的参数 ...可变参数的意思 
     * @return 调用方法后的返回值 
     */  
    public Object invoke(String className, String methodName, Object ... args) {  
        Object obj = null;  
        try {  
            obj = Class.forName(className).newInstance();  
            return invoke(obj, methodName, args);  

        } catch (InstantiationException e) {  
            e.printStackTrace();  
        } catch (IllegalAccessException e) {  
            e.printStackTrace();  
        } catch (ClassNotFoundException e) {  
            e.printStackTrace();  
        }  
        return invoke(null, methodName, args);  
    }  
    /** 
     * @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 {  
            //2、执行Method方法  

            Method method = getMethod(obj.getClass(), methodName,parameterTypes);  

            //通过反射执行private方法  
            method.setAccessible(true);  

            //3、返回方法的返回值  
            return method.invoke(obj,args);  

        } catch (Exception e) {  

        }  

        return null;  
    }  
    public void  testInvoke(){
        Object obj = new TMethod();

           invoke(obj, "test3","test3",10);  

            Object result = invoke(obj, "test2","test2");  
            System.out.println(result); 
    }
     public static void main(String[] args) {
         try {

             TInvoke obj = new TInvoke();  
               obj.testInvoke();
        } catch (Exception e) {
            e.printStackTrace();
        }  
    }

}

1、如上,我们将方法名,方法参数和类对象或者类的class对象传递给invoke方法
invoke(String className, String methodName, Object … args),当我们传递的参数包含int,boolean等是会自动装箱成Integer,Boolean

2、接下来我们根据invoke方法参数获取需要执行方法参数的Class类型,进而根据方法名称和方法的参数的Class类型获取需要执行的方法对象
clazz.getDeclaredMethod(methodName, parameterTypes);

3、 进而执行方法
method.invoke(obj,args);

4、以上代码输出如下

java.lang.NoSuchMethodException: reflect.TMethod.test3(java.lang.String, java.lang.Integer)
    at java.lang.Class.getDeclaredMethod(Class.java:2130)
    at reflect.TInvoke.getMethod(TInvoke.java:13)
    at reflect.TInvoke.invoke(TInvoke.java:57)
    at reflect.TInvoke.testInvoke(TInvoke.java:74)
    at reflect.TInvoke.main(TInvoke.java:83)
私有测试方法2,参数String=test2
null

可以看到找不到方法,因为方法的参数类型是(java.lang.String ,int)类型,而我们获取的是(java.lang.String, java.lang.Integer)类型,与实际的方法参数类型不符,无法找到该方法

这是由于int类型的自动封装造成的,那么该怎么解决呢?

我们获取方法的参数类型不对,在根据参数获取参数类型的时候出错,那么我们就从根源上解决这个问题

在传递参数的同时,传递方法参数的类型,手动传入参数类型就不会出现根据参数获取参数类型的错误了

通用解决方法

package reflect;

import java.lang.reflect.Method;

public class TInvokeT {
     /** 
     * 获取clazz 的methodName 方法, 该方法可能是私有方法 
     */  
    public Method getMethod(Class clazz, String methodName, Class ... parameterTypes) {  
        //注意这个循环里的内容!!! 
        for (; clazz != Object.class; clazz = clazz.getSuperclass()){  
            try {  
                return clazz.getDeclaredMethod(methodName, parameterTypes);  
            } catch (Exception e) { 
                e.printStackTrace();
            }  
        }  
        return null;  
    }  
   /** 
     * @param className  某个类的全类名 
     * @param methodName 类的一个方法的方法名,该方法也可能是私有方法 
     * @param args  调用该方法需要传入的参数 ...可变参数的意思 
     * @return 调用方法后的返回值 
     */  
    public Object invoke(String className, String methodName,Class<?>[] parameterTypes,Object ... args) {  
        Object obj = null;  
        try {  
            obj = Class.forName(className).newInstance();  
            return invoke(obj, methodName, parameterTypes,args);  

        } catch (InstantiationException e) {  
            e.printStackTrace();  
        } catch (IllegalAccessException e) {  
            e.printStackTrace();  
        } catch (ClassNotFoundException e) {  
            e.printStackTrace();  
        }  
        return invoke(null, methodName,parameterTypes, args);  
    }  
    /** 
     * @param obj  方法执行的那个对象 
     * @param methodName 类的一个方法的方法名,该方法也可能是私有方法,还可能是该方法在父类中定义的私有方法 
     * @param args  调用该方法需要传入的参数 ...可变参数的意思 
     * @return 调用方法后的返回值 
     */  
    public Object invoke(Object obj, String methodName,Class<?>[] parameterTypes, Object ... args) {  
        try {  
            //2、执行Method方法  

            Method method = getMethod(obj.getClass(), methodName,parameterTypes);  

            //通过反射执行private方法  
            method.setAccessible(true);  

            //3、返回方法的返回值  
            return method.invoke(obj,args);  

        } catch (Exception e) {  

        }  

        return null;  
    }  
    public void  testInvoke(){
        Object obj = new TMethod();

           invoke(obj, "test3",new Class<?>[] {String.class,int.class},"test3",10);  

            Object result = invoke(obj, "test2",new Class<?>[] {String.class},"test2");  
            System.out.println(result); 
    }
     public static void main(String[] args) {
         try {
             TInvokeT obj = new TInvokeT();  
               obj.testInvoke();
        } catch (Exception e) {
            e.printStackTrace();
        }  
    }

}

输出如下

公有测试方法3,参数String=test3:num=10
私有测试方法2,参数String=test2
null

invoke(obj, “test2”,new Class[] {String.class},”test2″);
invoke方法在传入参数值的同时传入参数的类型的数组

invoke(Object obj, String methodName,Class[] parameterTypes, Object … args)
invoke方法获取参数值的同时获取参数的类型,直接使用参数类型,不必获取就不存在参数类型获取错误的问题

点赞

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注