chris01
chris01

Reputation: 12321

Java: How to select/call a function by a strings content?

I have a list and I have functions.

I want to iterate the list and call the function that matches the lists element. How can I do that in a more elegant way than comparing the name in a if or switch?

class C
{
  String [] lst = {"foo", "bar", "zoo"};

  void foo () { /* ... */ }
  void bar () { /* ... */ }

  void NotSoElegant ()
  {
    for (String s : lst)
    {
      if (s.equals ("foo") == true)
      { foo (); }
      if (s.equals ("bar") == true)
      { bar (); }
    }
  }
}

Upvotes: 2

Views: 579

Answers (2)

Use the Replace Conditional with Polymorphism refactoring along with lambdas/method references. Assuming that your methods don't take parameters and don't return anything, they match the Runnable interface:

class MoreElegant {

  static final Map<String, Runnable> COMMANDS = Map.of(
    "foo", MoreElegant::foo,
    "bar", MoreElegant::bar,
    "baz", () -> { doSomethingElse(); }
  );

  void execute(List<String> commands) {
    commands.forEach(c ->
      COMMANDS
        .getOrDefault(c, () -> throw new IllegalArgumentException("no command " + c))
        .run()
    );
  }
}

Upvotes: 3

m.antkowicz
m.antkowicz

Reputation: 13571

I strongly advise against to use reflection in such case - it's obviously code smell, it's breaching the security of your code and may cause many, many issues and drawbacks - just think what will happen if someone will put NotSoElegant in the list.

Of course there are methods to fetch method by name so basically you could scan the class, get method by string, handle exceptions... Do not do this.

Basically there is nothing bad in having such set of ifs however you can refactor this a little bit using switch statement

for (String s : lst) {
    switch(s) {
        case "foo": 
            foo();
            break;
        case "bar": 
            bar();
            break;
    }
}

If you want to be more SOLID complain and do not break Open-Closed rule you should rather think about using some design patterns (like Strategy) but do not use reflection :)

Upvotes: 5

Related Questions