Hey there,

I'm stuck in a rut at the moment trying to figure something out. I have a class, that has 4 methods. method1(), method2(), method3() and whatMethod()...

whatMethod() accepts a String and then decides what method to execute based on the received String. Say the String that was sent to whatMethod() was "method2", then whatMethod() will execute method2()...

How would you go about doing this? I've been sitting here trying to figure out how but I seem to be a bit slow today...

Thank in advance!

You are just not seeing simple image

if(string.equals("name1"))
    method1();
else if(string.equals("name2"))
    method2();
else if(string.equals("name3"))
    method3();

Boy do I feel stupid right now...
There is no shorter way of doing this? The actual application I'm using this idea on has like 25+ methods in the class. So would the only way be by itterating through 25+ if,else() statements?

Then you should seriously refactor what ever you doing because that is way to much. If you describe problem little more in detail I'm sure someone can come with some good idea...

I doesn't see any differencies between if - esle if - else and switch- default, nor with performancies,

:-) and doesn't call that applications semaphore if contains only 25 methods :-)

mKorbel,
I never said that switch-case is going to impact the performance in any way whatsoever. however, I think there is a reason why they built the switch-case construct, and I think the reason is to make code easier to write. and since Dean_Grobler asked if he has to write 25 if-else statements, implying he'd rather not, I thought I'd remind him of the switch-case construct... whatever.

You can use Reflection to execute a method given its name in a String. Something along the lines of:

import java.lang.reflect.Method;
   public void invokeByName(String name) throws Exception {
      Method method = this.getClass().getDeclaredMethod(name);
      // throws NoSuchMethodException if method is not found
      method.invoke(this);
      // may throw IllegalAccessException,IllegalArgumentException, InvocationTargetException
   }
Comments
Exactly what I was looking for, thank you so much!

@ bibiki

again not

if - else

, but

if - else if - else

, that's same as swith - default, as you said sure - whatever, because we're on public Forum, isn't it

@ JamesCherrill

interesting

if you just want to avoid using if-else for all 25 cases, you can use switch-case.

He's using Strings, so unless you are on a pre-release Java 7 that's not really going to fly.

I am a little confused here, James. let me explain what exactly I have been thinking, giving some sample code:

public void pickWhichMethodToRun(String s){

     switch(s){
         case "method1":
               method1();
               break;

         case "method2":
               method2();
               break;
         .
         .
         .
         .

         case "method25":
               method25();
               break;

         default:
             System.out.println("haven't picked an existing method");
     }

}

what do you think James? would this work? or should I just try it in some code?

No that won't work. Java doesn't support switches on Strings, just integers and enums. Java 7 has switches on Strings, but it's not released yet.

James,
I tried the code I just wrote, and realized that one can't use switch with data types other than byte, short, char, and int. although my way of doing this task is possible, seems like it is a little laborious.

another lesson learned, and the same mistake repeated (don't ever second guess experience)

I'm not sure what is being done that would require runtime selection between 25 different methods, but perhaps a command pattern inner class implementation for the actions and a hashmap to map them to your strings might work out.

one can't use switch with data types other than byte, short, char, and int

... amd enums, don't forget. One standard work-round for the lack of switches on Strings is to create an enum, with member names to match the strings, then use valueOf(...) to convert the String to an enum value that can be used in a switch. Yes, I know, it's tacky. Roll on Java 7!

It seems to me that we're missing the point somewhat. If-chains are best when they're refactored out of your code, and switches likewise should be mercilessly eliminated whenever possible.
Reflection gets you somewhere, (and James, I'm playing with some ideas to make this even easier - I haven't left the previous discussion behind!) but stepping back, I have a simple question:
Is there really no way do to this in an object-oriented fashion?

Dean - can you walk us through the actual problem here? I don't need to see all of your code, but sketch out the design, and what these methods are doing. Maybe you can do this in a reasonable fashion.

Edited 5 Years Ago by jon.kiparsky: n/a

I am aware that I might sound like I'm taking it personal, but I really am not, I assure you... however, kiparsky, I would like to know why is it that switches are a no-no. is it just because of the reasons we already mentioned, or is there anything else as well?

> Is there really no way do to this in an object-oriented fashion?
An action map as I mentioned above

class SomeAction{
  public execute(){}
}

mapped to strings or an enum or he could consider a state pattern.

More information about the specifics of the problem would definitely help.

I am aware that I might sound like I'm taking it personal, but I really am not, I assure you... however, kiparsky, I would like to know why is it that switches are a no-no. is it just because of the reasons we already mentioned, or is there anything else as well?

Well, they're messy, to start with. When you start dealing with a switch, you know one thing and that's that you've got to deal with every branch, right here. And if you want to make it at all readable, you end up defining a method for each case, and just calling that method:

case 0 : calculateAndDisplay(a, b, c); break;
case 1 : refreshDisplay; break;

rather than

case 0 : 
  a = b+1;
  c = callSomeMethod(a);
  gui.displayResults(a, b, c);
  break;
case 1 : 
  // lots of code to refresh display, too tired to make that up just now;
  break;

So we're defining an action in one place and calling it in another. This provides a degree of readability - now reading the switch means reading a bunch of high-level stuff that actually tells you what's going on, instead of trying to figure out what all these method calls mean each time.

But notice that now we've made the switch irrelevant. Instead of calling the switch, could we not just call on an array? Yes, we could:

actions[n].execute();

where each object in actions is a Command action, as James suggests.

public class CalculateAndDisplay extends Command{
public void execute(int a, int b, int c)
  {
    a = b+1;
    c = callSomeMethod(a);
    gui.displayResults(a, b, c);
  }
}

(what's a gui? well, the abstract class Command knows about that, so this class does as well, by extension.)


If you want to provide some readability, used named constants for your actions:

public static final int CALCULATE_AND_DISPLAY = 0;
public static final int REFRESH_DISPLAY = 1;

Command[] actions = new Command[10]; //or however many, or make it an ArrayList, or whatever

actions[CALCULATE_AND_DISPLAY] = new CalculateAndDisplay();
actions[REFRESH_DISPLAY] = new RefreshDisplay();

But that turns out not to be necessary.

Now you can define your Commands in a Class, and all of that functionality is gathered in one place, where you can look at it if you need it, or ignore it if you have other problems.

But it can get better still. This looks like an action handler. That means something's firing an action, doesn't it? Well, that something should know at any moment what action it's firing. If your Command objects are actionListeners... well, they just fire their own execute() method, right? So your decision-handling is now entirely message-passing.

And isn't that a bit nicer than good old procedural slog?

In an object-oriented language, we're dealing with objects. What we want is to say: "Object, go do your thing". Then, if we care what that object does, we go and look.
If you're writing if-chains and switches, it's a pretty good bet that you need to go back and look at your design and see what you've done wrong.

Edited 5 Years Ago by jon.kiparsky: n/a

Comments
really good

Wow. This has turned into a (very interesting) debate about how to associate arbitrary blocks of code with arbitrary names, and that is a real Java problem, but it's not what DeanGrobler asked:

whatMethod() accepts a String and then decides what method to execute based on the received String. Say the String that was sent to whatMethod() was "method2", then whatMethod() will execute method2()... How would you go about doing this?

I guess my original post may have been too cryptic, so here's a better explanantion:

Given the name of a (no args) method in String name, the following line of code executes the method:

getClass().getDeclaredMethod(name).invoke(this);

Realistically, just how simple do you want this to be?

With error handling, and packaged as a method it's still not hard:

void whatMethod(String name) {
      try {
         getClass().getDeclaredMethod(name).invoke(this);
      } catch (Exception e) {
         System.out.println(e);
      }
   }

Finally, in 17 easy lines, here's a complete runnable demo of it in action:

public class Demo {

   void whatMethod(String name) {
      try {
         getClass().getDeclaredMethod(name).invoke(this);
      } catch (Exception e) {
         System.out.println(e);
      }
   }

   void method1() {  System.out.println("Method 1 called"); }

   public static void main(String[] args) {
      new Demo().whatMethod("method1"); // should call method1()
      new Demo().whatMethod("method2"); // should error - no such method
   }
}
Comments
Nice sample James
This article has been dead for over six months. Start a new discussion instead.