15-100 Lecture 9 (Monday, June 8, 2006)

A Simple Tangle

Let's write some quick code. Given a user's choice, represented as a char, let's print my 'F'irst, 'M'iddle, or 'L'ast name, or 'Q'uit.

```  boolean quit = false;

while (!quit) {

System.out.println ("");
System.out.println ("");
System.out.println ("F)irst name");
System.out.println ("M)iddle name");
System.out.println ("L)ast name");
System.out.println ("Q)uit");
System.out.println ("");

// Get choice
char choice = choiceString.toUpperCase().charAt(0);

// Decide what to do -- and do it
if (choice == 'F')
System.out.println ("Gregory");
else
if (choice == 'M')
System.out.println ("Michael");
else
if (choice == 'L')
System.out.println ("Kesden");
else
if (choice == 'Q')
quit = true; // or break
else
System.out.println ("Please select F, M, L, or Q.");
}
```

Notice how nested that code became. Does it have to be that complicated? Well, we can rewrite it and make it a bit better. To do that, we'll bail as soon as we get a match, so we can eliminate the nesting:

```  boolean quit = false;

while (!quit) {

System.out.println ("");
System.out.println ("");
System.out.println ("F)irst name");
System.out.println ("M)iddle name");
System.out.println ("L)ast name");
System.out.println ("Q)uit");
System.out.println ("");

// Get choice
char choice = choiceString.toUpperCase().charAt(0);

// Decide what to do -- and do it
if (choice == 'F') {
System.out.println ("Gregory");
continue;
}

if (choice == 'M') {
System.out.println ("Michael");
continue;
}

if (choice == 'L') {
System.out.println ("Kesden");
continue;
}

if (choice == 'Q') {
quite = true; // Or simply, "break;" and skip the next line
continue;
}

System.out.println ("Please select F, M, L, or Q.");
}
```

The above construction is better. But, it highlights the problem. We're trying to make a one-of-n decision, given a construct, the if-else, that is designed to make a one-of-two decision. So, we basically build up the the right number of choices in powers of two.

The Switch Statement

Java's switch statement is designed to support decision making where there are more than two possibilities. You provide a laundry-list of possibilities. Which of them, if any, are selected depend on a single predicate.

Within the switch statmeent, there is a laundry list of "cases". Execution procedes down this laundry list. Nothing happens until one of the cases actually matches the value of the predicate. At that point, a "big switch in the sky" is thrown and everything thereafter is executed. And, everything means everything -- even if it is associated with a case that doesn't match. This is because the switch is already thrown.

To avoid this behavior, so that exactly one path can be selected, the code associated with each case is often followed by a "break statment". It works as it did within a loop. A "break" casues control to immediately leave the switch and pick up after it.

Additionally, the "default" case can be specified. This case matches anything. It alwasy cases the great switch in the sky to be turned on.

This is best illustrated with an example. Let's consider our program of last class, rewritten using a switch.

Detangled with Switch

Rememebr this program? Look how pretty it is:

```  boolean quit = false;

while (!quit) {

System.out.println ("");
System.out.println ("");
System.out.println ("F)irst name");
System.out.println ("M)iddle name");
System.out.println ("L)ast name");
System.out.println ("Q)uit");
System.out.println ("");

// Get choice
char choice = choiceString.toUpperCase().charAt(0);

// Decide what to do -- and do it
switch (choice) {

case 'F':
System.out.println ("Gregory");
break;

case 'M':
System.out.println ("Michael");
break;

case 'L':
System.out.println ("Kesden");
break;

case 'Q':
// Notice: Can't just break here -- we'd leave the switch, not the loop
quit = true;
break;

default:
// Since this is the last case, not strictly necessary, but good form
System.out.println ("Please select F, M, L, or Q.");
break;

}

}
```

...wasn't that nice?

A Closer Look at the Break (or Absence, Thereof)

Now, let's take a closer look at the break. Let's see how we can avoid the need to upperCase() the string, by accepting either lower- or upper-case, directly.

```  boolean quit = false;

while (!quit) {

System.out.println ("");
System.out.println ("");
System.out.println ("F)irst name");
System.out.println ("M)iddle name");
System.out.println ("L)ast name");
System.out.println ("Q)uit");
System.out.println ("");

// Get choice
char choice = choiceString.charAt(0);

// Decide what to do -- and do it
switch (choice) {

case 'f':
case 'F':
System.out.println ("Gregory");
break;

case 'm':
case 'M':
System.out.println ("Michael");
break;

case 'l':
case 'L':
System.out.println ("Kesden");
break;

case 'q':
case 'Q':
// Notice: Can't just break here -- we'd leave the switch, not the loop
quit = true;
break;

default:
// Since this is the last case, not strictly necessary, but good form
System.out.println ("Please select F, M, L, or Q.");
break;

}

}
```

Take a look at the back-to-back use of upper- and lower-cases. This works because there is no break after the first case -- only the second. So, if the lower case "turns the switch on", it stays on until it hits the break.

Switch Statment, Important Notes

A few things to keep in mind:

• The "switch" must be based on an "ordinal" type: int, long, char, boolean. It can't be based on somethng that requires complicated matching, such as float, double, String (or any Object), &c.

• The "default" case is not requied. It is completely optional.

• You should always end a case with a break -- even if it is the last one. During maintenance, someone might just add a new case underneath without noticing the absence of the break.