damon
damon

Reputation: 8467

using reflection to invoke methods which takes different parameters

I have two methods in a class ,one takes a Comparable[] as parameter and returns a Boolean value.The other method takes a Comparable[] and an int value ,returning a Boolean.I tried to write some methods to invoke the methods using reflection..

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;       
    }
}

The first method invocation( ie, isTooBig()) works when the argument (which is a String[]) is wrapped in an Object[] .. But this fails for the next method invocation which takes a String[] and an int..

How do I correct this?

Upvotes: 1

Views: 7243

Answers (4)

user2511414
user2511414

Reputation:

Easy buddy, the problems(2)

1 . you pass the String array as Object array to the callMethod() function, while you need to pass the String array as one argument, but it will passed as 5 arguments, simple just replace this code

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

to this

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

this ensures you the whole array will passed as one argument.

2 . and another issue, you call the method (this this.methodTocall.invoke(null, new Object[]{args})) with just one argument again, in fact with second call you put all the arguments as one argument with Object[]{args} and invoke the method. so change this line

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

with this

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

Upvotes: 1

johnchen902
johnchen902

Reputation: 9601

  1. In callMethod, args is already an array. You don't need to wrap it:

    result = this.methodTocall.invoke(null, args);
    
  2. In main, the warning (in Eclipse) is clear enough:

    The argument of type String[] should explicitly be cast to Object[] for the invocation of the varargs method callMethod(Object...) from type MethodCalling. It could alternatively be cast to Object for a varargs invocation

    Or the warning given by javac

    warning: non-varargs call of varargs method with inexact argument type for last parameter;

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

    cast to Object for a varargs call

    cast to Object[] for a non-varargs call and to suppress this warning

    Solution:

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

Upvotes: 2

f1sh
f1sh

Reputation: 11934

The problem here is in the line

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

When you pass arguments to the method, you wrap them in another Object[], which is a) unnecessary and, when args contains multiple arguments (like the string and the int from your second method call), hides those arguments in the Object array, making them appear as one parameter. That is why you get the error.

Solve it by using the following changes:

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

Then change your main method to this:

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);

Upvotes: 1

sp00m
sp00m

Reputation: 48807

You need to declare your String array as an object:

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

And to use directly the args arguments for the invoke method:

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

Upvotes: 0

Related Questions