1

我在一个类中有两个方法,一个接受一个Comparable[]作为参数并返回一个Boolean值。另一个方法接受一个Comparable[]和一个int值,返回一个Boolean。我尝试编写一些方法来使用反射调用这些方法。

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class MethodCalling {
    private static Class classTocall;
    private static Method methodTocall;

    public MethodCalling(String classname){
        super();
        try {
            this.classTocall = Class.forName(classname);
        } catch (ClassNotFoundException e) {
            System.out.println("failed to get class!!");
            e.printStackTrace();
        }
    }

    public void setMethod(String method,Class...args){
        try {
            this.methodTocall = this.classTocall.getMethod(method, args);
        } catch (SecurityException e) {

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

            e.printStackTrace();
        }
    }

    public Object callMethod(Object...args){
        Object result = null;

        try {
            if(this.methodTocall != null){
                result = this.methodTocall.invoke(null, new Object[]{args});

            }
        } catch (IllegalArgumentException e) {

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

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

            e.printStackTrace();
        }
        return result;
    }

    public static void main(String[] args) {
        String[] a = new String[]{"H","E","L","L","O"};
        MethodCalling mc = new MethodCalling("SizeChecker");
        mc.setMethod("isTooBig", Comparable[].class);
        Boolean result1 = (Boolean) mc.callMethod(a);
        System.out.println("too big="+result1);


        mc.setMethod("isCorrectLength",Comparable[].class,int.class);
        Boolean result2 = (Boolean) mc.callMethod(a,5);
        System.out.println("length is 5="+result2);
    }
}

class SizeChecker{  
    public static boolean isTooBig(Comparable[] a){
        return a.length > 10;
    }   
    public static boolean isCorrectLength(Comparable[] a,int x){
        return a.length == x;       
    }
}

当参数(即 a )被包裹在一个. 中时,第一个方法调用(即isTooBig())起作用。但是对于采用 a和一个 int的下一个方法调用,这将失败。String[]Object[]String[]

我该如何纠正?

4

4 回答 4

2
  1. callMethod,args已经是一个数组。你不需要包装它:

    result = this.methodTocall.invoke(null, args);
    
  2. main中,警告(在 Eclipse 中)很清楚:

    type 的参数String[]应该显式地转换为从 typeObject[]调用 varargs 方法。也可以将其强制转换为 varargs 调用callMethod(Object...)MethodCallingObject

    或者给出的警告javac

    警告:最后一个参数的参数类型不准确的可变参数方法的非可变参数调用;

    Boolean result1 = (Boolean) mc.callMethod(a);
                                             ^
    

    转换Object为可变参数调用

    强制转换Object[]为非可变参数调用并抑制此警告

    解决方案:

    Boolean result1 = (Boolean) mc.callMethod((Object) a);
    
于 2013-07-16T13:25:49.207 回答
1

这里的问题在于

result = this.methodTocall.invoke(null, new Object[]{args});

当您将参数传递给方法时,您将它们包装在另一个 Object[] 中,这是 a) 不必要的,并且当args包含多个参数(如第二个方法调用中的字符串和 int)时,将这些参数隐藏在Object数组中,使它们作为一个参数出现。这就是你得到错误的原因。

通过使用以下更改来解决它:

result = this.methodTocall.invoke(null, args);

然后将您的主要方法更改为:

String[] a = new String[]{"H","E","L","L","O"};
MethodCalling mc = new MethodCalling("wat.SizeChecker");
mc.setMethod("isTooBig", Comparable[].class);
/* change here: place the single parameter into a parameter array */
Boolean result1 = (Boolean) mc.callMethod(new Object[]{a});
System.out.println("too big="+result1);

mc.setMethod("isCorrectLength",Comparable[].class, int.class);
/* since the callMethod accepts varargs, these are automatically placed in an Object[] */
Boolean result2 = (Boolean) mc.callMethod(a, 5);
System.out.println("length is 5="+result2);
于 2013-07-16T13:27:35.260 回答
1

简单的哥们,问题(2)

1. 您将字符串数组作为对象数组传递给callMethod()函数,而您需要将字符串数组作为一个参数传递,但它将作为 5 个参数传递,只需替换此代码即可

Boolean result1 = (Boolean) mc.callMethod(a);

对此

Boolean result1 = (Boolean) mc.callMethod(new Object[]{args});

这可以确保您将整个数组作为一个参数传递。

2. 另一个问题是,您this.methodTocall.invoke(null, new Object[]{args})再次仅使用一个参数调用方法(this),实际上在第二次调用时,您将所有参数作为一个参数Object[]{args}并调用该方法。所以改变这一行

result = this.methodTocall.invoke(null, new Object[]{args});

有了这个

result = this.methodTocall.invoke(null, args);
于 2013-07-16T14:41:00.040 回答
0

您需要将 String 数组声明为对象:

Object a = new String[] { "H", "E", "L", "L", "O" };

并直接使用args该方法的参数invoke

result = this.methodTocall.invoke(null, args);
于 2013-07-16T13:26:25.147 回答