Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java reflection API and invoking a method with variable number of arguments

I have a problem trying to solve a situation, when I use Java Reflection API to invoke a method that accepts a variable number of parameters. Every time I try to do that I get an "NoSuchMethodException".

My declaration of method to invoke:

public void AddShow(String movieName, String cinemaName, String... days) {
}

And the code for the method that does the invocation:

public void Exec(String command){
    try {
        String[] words = command.split(" ");
        String commandName = words[0];
        Class<? extends UserInterface> thisClass = (Class<? extends UserInterface>)getClass();
        Class<String>[] par = new Class[words.length-1];
        String[] params = new String[words.length-1];
        for(int i = 1; i< words.length; i++){
            params[i-1] = words[i];
            try {
                par[i-1] = (Class<String>) Class.forName("java.lang.String");
            } catch (ClassNotFoundException e) {
                System.out.println("If this shows up, something is siriously wrong... Waht have you done?!");
            }
        }
        Method method;
        if(par.length != 0) {
            method = thisClass.getMethod(commandName, par);
            method.invoke(new UserInterface(CinemaDb), (Object[])params);
        } else {
            method = thisClass.getMethod(commandName);
            method.invoke(new UserInterface(CinemaDb));
        }
    } catch (SecurityException e) {
        System.out.println("Security error, sry again.");
    } catch (NoSuchMethodException e) {
        System.out.println("Wrong command, try again (check the parameters)!");
    } catch (IllegalAccessException e) {
        System.out.println("You don't have access rights, try again.");
    } catch (IllegalArgumentException e) {
        System.out.println("Wrong arguments, try again.");
    } catch (InvocationTargetException e) {
        System.out.println("Invocation error, try again.");
    }
}

If you know how can I change my Exec method to solve this problem, I will be really grateful.

Thanks!

like image 581
domderen Avatar asked Dec 27 '22 12:12

domderen


2 Answers

varargs in Java are implemented via arrays, so the parameters are String.class, String.class, and String[].class.

like image 192
TofuBeer Avatar answered Jan 12 '23 04:01

TofuBeer


The varargs part is represented as String[] after compilation, so use String[].class

In your case it will be a bit harder, since you can't know exactly how many of the arguments there are before the varargs. So if you invoke showFoo str1 str2 str3 str4 you can't know how many string arguments there are before the varargs.

So you can put a delimiter in your command string, which will tell the parser where to add the String[].class. Another option is to simply call getMethods() and get the required method only by its name (iterate and compare the names). But you won't be able to use overloading.

That said, I don't think it is a really good idea to have such a specially-formatted string for reflective executions (unless it comes from an external system, but then it might be a security issue)

like image 32
Bozho Avatar answered Jan 12 '23 02:01

Bozho