Andreas
Andreas

Reputation: 7550

How to call a method by name (String) in Java?

Every instance of class A has an instance of class B. A should call different methods in B depending on its member variable method_num. This is an implementation that does what I want:

public class A {
    private B myB = new B();
    public int method_num = 1;
    public callBMethod() {
        if ( method_num == 1 )
            myB.method1();
        else
            myB.method2();
    }
}

public class B {
    public method1() { }
    public method2() { }
}

But instead of doing myA.method_num = 1, I want to be able to somehow pass B's method1 or method2 directly. How can I do that?

Upvotes: 0

Views: 8162

Answers (5)

Woot4Moo
Woot4Moo

Reputation: 24316

I think you can use reflection like this:

java.lang.reflect.Method method;
try {
  method = obj.getClass().getMethod(methodName, param1.class, param2.class, ..);
} catch (SecurityException e) {
  // ...
} catch (NoSuchMethodException e) {
  // ...
}  

try {
  method.invoke(obj, arg1, arg2,...);
} catch (IllegalArgumentException e) {  //do proper handling
} catch (IllegalAccessException e) {//do proper handling
} catch (InvocationTargetException e) {//do proper handling

Upvotes: 5

OldCurmudgeon
OldCurmudgeon

Reputation: 65793

If you don't want to use reflection (and this is an excellent goal) then there are some neat features of enums that allow you to set up an enum as a proxy.

public class A {
  private B myB = new B();
  public int method_num = 1;

  public void callBMethod() {
    // Could do it by name.
    BMethods.valueOf("method1").call(myB);
    // Or by number.
    BMethods.values()[method_num].call(myB);
  }

}

enum BMethods{
  method1 {
    @Override
    public void call(B b) {
      b.method1();
    }
  },
  method2 {
    @Override
    public void call(B b) {
      b.method2();
    }
  };

  public abstract void call (B b);
}

public class B {
  public void method1() {
  }

  public void method2() {
  }

}

Upvotes: 4

Gyanendra Dwivedi
Gyanendra Dwivedi

Reputation: 5538

Java reflection API provides you a way, where a Method type of object could be passed along with the target object and then the method could be invoked on the target object.

A sample example is here:

Method m; // The method to be invoked

  Object target; // The object to invoke it on

  Object[] args; // The arguments to pass to the method

  // An empty array; used for methods with no arguments at all.
  static final Object[] nullargs = new Object[] {};

  /** This constructor creates a Command object for a no-arg method */
  public Command(Object target, Method m) {
    this(target, m, nullargs);
  }

  /**
   * This constructor creates a Command object for a method that takes the
   * specified array of arguments. Note that the parse() method provides
   * another way to create a Command object
   */
  public Command(Object target, Method m, Object[] args) {
    this.target = target;
    this.m = m;
    this.args = args;
  }

  /**
   * Invoke the Command by calling the method on its target, and passing the
   * arguments. See also actionPerformed() which does not throw the checked
   * exceptions that this method does.
   */
  public void invoke() throws IllegalAccessException,
      InvocationTargetException {
    m.invoke(target, args); // Use reflection to invoke the method
  }

Upvotes: 0

johan d
johan d

Reputation: 2863

Maybe with Runnable objects ? You can pass from B a runnable, and call .run() directly from A

Upvotes: 2

duffymo
duffymo

Reputation: 308743

You cannot. Java doesn't treat functions as first class objects, because it doesn't have functional features like Python or C#.

You can create a Command interface and pass that object reference:

public interface Command {
    void execute(Object [] args);
}

Upvotes: 3

Related Questions