4

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!

3
  • 1
    Your Exec method should be named exec, and instead of doing Clas.forName("java.lang.string"), you may just do String.class : much shorter and safer. Commented Oct 30, 2011 at 22:22
  • Why should it me named "exec"? Because of the naming conventions or are you refering to anything else. And thanks for the tip, it made my code clearer. Commented Oct 30, 2011 at 22:25
  • Yes, to respect the Java naming conventions. Methods always start with a lower-case letter in Java. Commented Oct 30, 2011 at 22:28

3 Answers 3

4

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

Sign up to request clarification or add additional context in comments.

1 Comment

Hmmm, is there any other way? Because I am not able to find out if the incomming String parameters are part of the Array or if they are just normal parameters...
3

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)

5 Comments

Yeah but I am using the same Exec method to run a couple more methods, so I am not able to find out is the incomming paramaters are part of Array or are they normal parameters
well, you can't because that's the scenario. Check my updated 3rd paragraph for an alternative, but generally, that's what it is.
Well you might be right, but I am creating a user interface, that accepts commands passed by user, so insted of creating one big switch to use every command I thought it might be easier and simpler to use the reflection API...
does the user input the commands as strings, containing method names? Can't he press buttons, for example
It is a command line tool, so not really. I tried to keep it as simple as possible, but I don't think there is a way to do it without adding additional character as delimiter in the command.
3

The Object[] holding the params should have two String params and String[], you're passing a flat String[].

2 Comments

Yeah but I am using the same Exec method to run a couple more methods, so I am not able to find out is the incomming paramaters are part of Array or are they normal parameters
@Tromax Nonetheless, that's the issue. You'll need to figure out a way to figure out what you need for the reflective call.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.