Search code examples
javacontrol-flow

Most concise way to express this Java conditional without checking a value twice


I have a variable, x.

I want to call a method m() only if x is one of two possible values.

When calling m(), I want to pass an argument to it, whose value depends on the value of x.

Is there a way to do this in Java without checking the value of x more than once, and calling/writing m() in one place only (i.e. not in multiple branches of an if statement)?

One solution I'm entertaining:

switch (x) {
  case 1:
    y = "foo";
    break;
  case 2:
    y = "bar";
    break;
  default:
    y = null;
    break;
}

if (y != null) m(y);

But I can't help but feel this is technically checking x twice, just obscuring this fact by adding a "proxy" for the second check.

(To clarify why the constraints are what they are: when reading code, I have a hard time understanding logic that branches a lot when there is a high degree of duplication between branches - it becomes a game of "spot the difference" rather than simply being able to see what is happening. I prefer to aggressively refactor such duplication away, which is a habit that serves me well in Ruby, JS, and other languages; I'm hoping I can learn to do the same for Java and make code easier for me and others to understand at a glance.)


Solution

  • Use "goto" or equivalent:

    void do_m_if_appropriate() {
    
      // x and y are assumed to be eg. member variables
    
      switch (x) {
    
        case 1:
          y = "foo";
          break;
    
        case 2:
          y = "bar";
          break;
    
        default:
          return; // this is the "goto equivalent" part
      }
    
      m(y);
    }
    

    Above is pretty elegant. If necessary, it's also trivial to change it to return true or false depending on if it called m(), or just y or null.


    You can also do tricks with loop constructs, though some might say this is abuse of the loop construct, and you should comment it accordingly:

    do { // note: not a real loop, used to skip call to m()
      switch (x) {
    
        case 1:
          y = "foo";
          break;
    
        case 2:
          y = "bar";
          break;
    
        default:
          continue; // "goto equivalent" part
      }
    
      m(y);
    } while(false);