1

We have X methods and we like call the one relative to user settings which of the following runs faster?

Case 1:

int userSetting = 1;
Method method = Class.getDeclaredMethod("Method" + userSetting);
method.invoke();


Case 2:

 int userSetting = 1;
 switch(userSettings) {
     case 0:
         Method0();
     break;
     case 1:
         Method1();
     break;
     ...
     ...
 }


Case 3:

int userSetting = 1;
if(userSetting == 0){
    Method0();
} else if(userSetting == 1){
    Method1();
} else....

Also:

  • You think one even if slower is better practice that the others? If yes why?
  • There is another way witch is better/faster...please tell us.

Thanks

mhaller
  • 14,122
  • 1
  • 42
  • 61
BrainCrash
  • 12,992
  • 3
  • 32
  • 38

5 Answers5

5

Option 1 uses reflection, and thus will probably be slower, as the javadocs indicate:

Performance Overhead
    Because reflection involves types that are dynamically resolved, certain Java 
    virtual machine optimizations can not be performed. Consequently, reflective 
    operations have slower performance than their non-reflective counterparts, 
    and should be avoided in sections of code which are called frequently in 
    performance-sensitive applications.

However it is easier to maintain this option then options 2+3.

I would suggest you to use a complete different option: use the strategy design pattern. It is more likely to be faster and much more readable then the alternatives.

amit
  • 175,853
  • 27
  • 231
  • 333
  • 1
    Am I correct if I say that the "strategy design pattern" you suggest is a step after we checked on witch method to call? Because I think we still need to check against the "userPreferences" before the calls... – BrainCrash Oct 16 '11 at 13:17
  • 1
    @BrainCrash: no, for example: you can create a `Map`, which is pre-populated with all your possible strategies with their matching Integers [this is done only once], and invoke `strategiesMap.get(userPrefs).strategyMethod()`. This solution is simple to program and will probably be much more readable, easier to maintain and almost surely faster then the alternatives. – amit Oct 16 '11 at 14:44
2

As amit points out, this is a case for the Strategy design pattern. Additionally, I want to give a short example:

Pseudo-Code:

public interface Calculator {
 public int calc(...);
}

public class FastCalc implements Calculator {
 public int calc(...) {
   // Do the fast stuff here
 }
}

public class SlowCalc implements Calculator {
 public int calc(...) {
   // Do the slow stuff here
 }
}

You main program then decides which strategy to use based on the user preferences:

 Calculator calc = userPreference.getBoolean("fast") ? new FastCalc() : new SlowCalc();
 int result = calc.calc(...);

This is because later, you can use the Factory pattern to create multiple strategies for various operations:

Factory factory = new SlowFactory();
Calculator calc = factory.createCalculator();
Operation op = factory.createSomeOtherOperation();


Factory factory = new FastFactory();
Calculator calc = factory.createCalculator();
Operation op = factory.createSomeOtherOperation();

As you can see, the code is the same for the Slow case and for the Fast case, except the factory class, and that you can create by deciding based on the user preference. Especially if you have more such operations, such as Calculator and my Operation example, then you will want your code to not be dependent on the user preference everywhere but only at a single place.

mhaller
  • 14,122
  • 1
  • 42
  • 61
0

Case 1 uses reflection and suffers a performance hit beyond approaches 2 and 3.

Between approaches 2 & 3 performance difference would be marginal at most. You must ask yourselves if any possible performance gain is really justified over code readability? Unless being on a truly limited microchip or similar I would always answer no.


Apart from the performance view, as @HoeverCraft Full Of Eels already pointed out you're probably better of redesigning your program to completely avoid the series of conditional clauses.

Community
  • 1
  • 1
Johan Sjöberg
  • 47,929
  • 21
  • 130
  • 148
0

I think the obvious slowest version is number one. reflexion is complex and is done during the runtime. for number 2 and number 3 you could have a look at Java: case-statment or if-statement efficiency perspective.

another way: could the configuration of the user change during the execution? if not, make the decision only one time on start-up.

Community
  • 1
  • 1
Thomas Uhrig
  • 30,811
  • 12
  • 60
  • 80
0

As all others have said #1 will most likely be the slowest.

The differences between 2 and 3 are negligible, but generally #2 shouldn't be slower than #3, because the compiler can change a switch to a cascaded if, if it thinks it would be faster. Also since the switch is clearly better readable than the if/else cascade I'd go with the second anyhow.

Although I'm extremely sure that this isn't the bottleneck anyhow - even if using reflection..

Voo
  • 29,040
  • 11
  • 82
  • 156