NeiL
NeiL

Reputation: 801

Passing parameters in generically implement methods in hashmap

I am following this question How to generically implement calling methods stored in a HashMap? I am trying to pass parameters while calling executeCommand function Example code is as follows, InvokesMethodItf

public interface InvokesMethodItf {

public void invokeMethod(String data) throws Exception; //pass the data as parameter
public void setMethod(Method method);
} 

InvokesMethod

public class InvokesMethod implements InvokesMethodItf{

private Method method;

@Override
public void invokeMethod(String data) throws Exception {
     method.invoke(data);    //pass the data to invoke (I think my problem is here). I dont know how to pass it.
}

@Override
public void setMethod(Method method) {
    this.method = method;
}

}

Terminal

public class Terminal {

public HashMap<Character, InvokesMethodItf> commands;

public Terminal() {
    this.commands = new HashMap<Character, InvokesMethodItf>();


}


private void setCommand(char letter, Method method) {

    InvokesMethodItf inv = new InvokesMethod();

    inv.setMethod(method);

    this.commands.put(letter, inv);
}

public void executeCommand(char letter, String data) throws Exception {
    this.commands.get(letter).invokeMethod(data);    //pass data to invoke method
 }
}

Main

    public class Main {           

    Terminal commandLine = new Terminal();
    commandLine.setCommand('h',test());   //This should give syntax error or i am not sure
    commandLine.executeCommand('h', "This is a test");

   public Method test(String data){
        Log.d("Test", data);

        return null;
    }
}

UPDATE: I am trying to set multiple methods using setCommand and execute it.

commandline.setCommand('p',this.getClass().getDeclaredMethod("parseData",String.class,Integer.class), this);
commandline.setCommand('p', this.getClass().getDeclaredMethod("test"), this);

Then , calling

commandline.executeCommand('p', "test", 2345);

Only test function is calling.(Last setCommand function is running). I think it is overwriting Method . Isn't there is someway to pass multiple methods in setCommand function. Changing type of Method to Method[] is not working either.

Upvotes: 1

Views: 1231

Answers (2)

sp00m
sp00m

Reputation: 48837

When invoking a method, you need to pass the instance from which the method should be invoked as well as the parameters:

public interface MethodInvoker {

    // the method + the instance from which the method should be called
    public void setMethod(Method method, Object instance);

    // invokes the method
    public void invoke(Object... params) throws Exception;

}

Here an implementation:

public class MethodInvokerImpl implements MethodInvoker {

    private Method method;
    private Object instance;

    @Override
    public void setMethod(Method method, Object instance) {
        this.method = method;
        this.instance = instance;
    }

    @Override
    public void invoke(Object... params) throws Exception {
        // first param: instance, then the parameters
        method.invoke(instance, params);
    }

}

Then your Terminal:

public class Terminal {

    public Map<Character, MethodInvoker> commands;

    public Terminal() {
        commands = new HashMap<Character, MethodInvoker>();
    }

    // instance needed, since MethodInvoker#setMethod needs it
    public void addCommand(char letter, Method method, Object instance) {
        MethodInvoker invoker = new MethodInvokerImpl();
        invoker.setMethod(method, instance);
        commands.put(letter, invoker);
    }

    public void executeCommand(char letter, Object... params) throws Exception {
        commands.get(letter).invoke(params);
    }

}

Finally in your main:

public void test(String data) {
    System.out.println(data);
}

public void main() throws Exception {
    Terminal commandLine = new Terminal();
    // #text() will be called from "this" instance
    commandLine.addCommand('h', getClass().getMethod("test", String.class), this);
    commandLine.executeCommand('h', "This is a test");
}

Note that static methods don't need instances since they belong to the class, e.g.:

public void main() throws Exception {
    Terminal commandLine = new Terminal();
    // simply pass "null" as instance
    commandLine.addCommand('h', getClass().getMethod("test", String.class), null);
    commandLine.executeCommand('h', "This is a test");
}

public static void test(String data) {
    System.out.println(data);
}

See https://stackoverflow.com/a/542122/1225328 and https://stackoverflow.com/a/1348228/1225328 as well.

Upvotes: 1

Kumar Abhinav
Kumar Abhinav

Reputation: 6675

Method is an Object which you will have to get using reflection.As I see the problems in your code,you cannot get Method Object using method invocation.Change this in your Main class.Check the javadoc here for getting Method Object from Class Object(for class Object you can use Class.forName(String class_binary_name) or Class literal

   public class Main {           

        Terminal commandLine = new Terminal();
        Method method = Main.class.getMethod("test",String.class);
        commandLine.setMethod('h',method); 
        commandLine.executeCommand('h', "This is a test");

        public void test(String data){
            Log.d("Test", data);

        }
    }

Also,change the return type of test class to void if you are not planning to return anything

Upvotes: 0

Related Questions