Chapter 11

How to Flick a Virtual Switch

IN THIS CHAPTER

check Dealing with many alternatives

check Jumping out from the middle of a statement

check Handling alternative assignments

Imagine playing Let’s Make a Deal with ten different doors. “Choose door number 1, door number 2, door number 3, door number 4 … Wait! Let’s break for a commercial. When we come back, I’ll say the names of the other six doors.”

What Monty Hall (the show’s host) needs is Java’s switch statement.

Meet the switch Statement

The code in Listing 9-2 (refer to Chapter 9) simulates a fortune-telling toy — an electronic oracle. Ask the program a question, and the program randomly generates a yes or no answer. But, as toys go, the code in Listing 9-2 isn’t much fun. The code has only two possible answers. There’s no variety. Even the earliest talking dolls could say about ten different sentences.

Suppose that you want to enhance the code of Listing 9-2. The call to myRandom.nextInt(10) + 1 generates numbers from 1 to 10. So maybe you can display a different sentence for each of the ten numbers. A big pile of if statements should do the trick:

if (randomNumber == 1) {
System.out.println("Yes. Isn’t it obvious?");
}
if (randomNumber == 2) {
System.out.println("No, and don’t ask again.");
}
if (randomNumber == 3) {
System.out.print("Yessir, yessir!");
System.out.println(" Three bags full.");
}
if (randomNumber == 4)
.
.
.
if (randomNumber < 1 || randomNumber > 10) {
System.out.print("Sorry, the electronic oracle");
System.out.println(" is closed for repairs.");
}

But that approach seems wasteful. Why not create a statement that checks the value of randomNumber just once and then takes an action based on the value that it finds? Fortunately, just such a statement exists: the switch statement. Listing 11-1 has an example of a switch statement.

LISTING 11-1 An Answer for Every Occasion

import java.util.Scanner;
import java.util.Random;
import static java.lang.System.out;

class TheOldSwitcheroo {

public static void main(String args[]) {
Scanner keyboard = new Scanner(System.in);
Random myRandom = new Random();
int randomNumber;

out.print("Type your question, my child: ");
keyboard.nextLine();

randomNumber = myRandom.nextInt(10) + 1;

switch (randomNumber) {
case 1:
out.println("Yes. Isn’t it obvious?");
break;

case 2:
out.println("No, and don’t ask again.");
break;

case 3:
out.print("Yessir, yessir!");
out.println(" Three bags full.");
break;

case 4:
out.println("What part of ’no’ don’t you understand?");
break;

case 5:
out.println("No chance, Lance.");
break;

case 6:
out.println("Sure, whatever.");
break;

case 7:
out.println("Yes, but only if you’re nice to me.");
break;

case 8:
out.println("Yes (as if I care).");
break;

case 9:
out.println("No, not until Cromwell seizes Dover.");
break;

case 10:
out.println("No, not until Nell squeezes Rover.");
break;

default:
out.print("You think you have problems?");
out.print(" My random number generator is broken!");
break;
}

out.println("Goodbye");

keyboard.close();
}
}

The cases in a switch statement

Figure 11-1 shows three runs of the program in Listing 11-1. Here’s what happens during one of these runs:

  • The user types a heavy question, and the variable randomNumber gets a value. In the second run of Figure 11-1, this value is 2.
  • Execution of the code in Listing 11-1 reaches the top of the switch statement, so the computer starts checking this statement’s case clauses. The value 2 doesn’t match the topmost case clause (the case 1 clause), so the computer moves on to the next case clause.
  • The value in the next case clause (the number 2) matches the value of the randomNumber variable, so the computer executes the statements in this case 2 clause. These two statements are

    out.println("No, and don’t ask again.");
    break;

    The first of the two statements displays No, and don’t ask again on the screen. The second statement is called a break statement. (What a surprise!) When the computer encounters a break statement, the computer jumps out of whatever switch statement it’s in. So, in Listing 11-1, the computer skips right past case 3, case 4, and so on. The computer jumps to the statement just after the end of the switch statement.

  • The computer displays Goodbye because that’s what the statement after the switch statement tells the computer to do.
image

FIGURE 11-1: Running the code of Listing 11-1.

The overall idea behind the program in Listing 11-1 is illustrated in Figure 11-2.

image

FIGURE 11-2: A fork with 11 prongs.

The default in a switch statement

What if something goes terribly wrong during a run of the Listing 11-1 program? Suppose that the expression myRandom.nextInt(10) + 1 generates a number that’s not in the 1-to-10 range. Then the computer responds by dropping past all the case clauses. Instead of landing on a case clause, the computer jumps to the default clause. In the default clause, the computer displays You think you have problems? … and then breaks out of the switch statement. After the computer is out of the switch statement, the computer displays Goodbye.

tip You don’t really need to put a break at the very end of a switch statement. In Listing 11-1, the last break (the break that’s part of the default clause) is just for the sake of overall tidiness.

Picky details about the switch statement

A switch statement can take the following form:

switch (Expression) {
case FirstValue:
Statements

case SecondValue:
MoreStatements

// … more cases …

default:
EvenMoreStatements
}

Here are some tidbits about switch statements:

  • The Expression doesn’t have to have an int value. It can be char, byte, short, or int.

    For example, the following code works in Java 5 and later:

    char letterGrade;
    letterGrade = keyboard.findWithinHorizon(".",0).charAt(0);

    switch (letterGrade) {
    case ’A’:
    System.out.println("Excellent");
    break;

    case ’B’:
    System.out.println("Good");
    break;

    case ’C’:
    System.out.println("Average");
    break;
    }

    In fact, if you avoid using the Scanner class and its findWithinHorizon method, this bullet’s switch statement works with all versions of Java — old and new.

  • If you use Java 7 or later, the Expression can be a String. For example, the following code doesn’t work with Java 6, but works well in Java 7:

    String description;
    description = keyboard.next();

    switch (description) {
    case "Excellent":
    System.out.println(’A’);
    break;

    case "Good":
    System.out.println(’B’);
    break;

    case "Average":
    System.out.println(’C’);
    break;
    }

    crossreference I introduce Java’s String type briefly in Chapter 8. I describe the String class with gusto in Chapter 18.

  • The Expression doesn’t have to be a single variable. It can be any expression of type char, byte, short, int, or String. For example, you can simulate the rolling of two dice with the following code:

    int die1, die2;

    die1 = myRandom.nextInt(6) + 1;
    die2 = myRandom.nextInt(6) + 1;

    switch (die1 + die2) {
    // … etc.

  • The cases in a switch statement don’t have to be in order. Here’s some acceptable code:

    switch (randomNumber) {
    case 2:
    System.out.println("No, and don’t ask again.");
    break;

    case 1:
    System.out.println("Yes. Isn’t it obvious?");
    break;

    case 3:
    System.out.print("Yessir, yessir!");
    System.out.println(" Three bags full.");
    break;

    // … etc.

    This mixing of cases may slow you down when you’re trying to read and understand a program, but it’s legal nonetheless.

  • You don’t need a case for each expected value of the Expression. You can leave some expected values to the default. Here’s an example:

    switch (randomNumber) {
    case 1:
    System.out.println("Yes. Isn’t it obvious?");
    break;

    case 5:
    System.out.println("No chance, Lance.");
    break;

    case 7:
    System.out.println("Yes, but only if you’re nice to me.");
    break;

    case 10:
    System.out.println("No, not until Nell squeezes Rover.");
    break;

    default:
    System.out.println("Sorry, I just can’t decide.");
    break;
    }

  • The default clause is optional.

    switch (randomNumber) {
    case 1:
    System.out.println("Yes. Isn’t it obvious?");
    break;

    case 2:
    System.out.println("No, and don’t ask again.");
    break;

    case 3:
    System.out.print("I’m too tired.");
    System.out.println(" Go ask somebody else.");
    }

    System.out.println("Goodbye");

    If you have no default clause, and a value that’s not covered by any of the cases comes up, the switch statement does nothing. For example, if randomNumber is 4, the preceding code displays Goodbye and nothing else.

  • In some ways, if statements are more versatile than switch statements. For example, you can’t use a condition in a switch statement’s Expression:

    //You can’t do this:
    switch (age >= 12 && age < 65)

    You can’t use a condition as a case value, either:

    //You can’t do this:
    switch (age) {
    case age <= 12: // … etc.

To break or not to break

At one time or another, every Java programmer forgets to use break statements. At first, the resulting output is confusing, but then the programmer remembers fall-through. The term fall-through describes what happens when you end a case without a break statement. What happens is that execution of the code falls right through to the next case in line. Execution keeps falling through until you eventually reach a break statement or the end of the entire switch statement.

If you don’t believe me, just look at Listing 11-2. This listing’s code has a switch statement gone bad.

LISTING 11-2 Please, Gimme a Break!

/*
* This isn’t good code. The programmer forgot some
* of the break statements.
*/
import java.util.Scanner;
import java.util.Random;
import static java.lang.System.out;

class BadBreaks {

public static void main(String args[]) {
Scanner keyboard = new Scanner(System.in);
Random myRandom = new Random();
int randomNumber;

out.print("Type your question, my child: ");
keyboard.nextLine();

randomNumber = myRandom.nextInt(10) + 1;

switch (randomNumber) {
case 1:
out.println("Yes. Isn’t it obvious?");

case 2:
out.println("No, and don’t ask again.");

case 3:
out.print("Yessir, yessir!");
out.println(" Three bags full.");

case 4:
out.println("What part of ’no’ don’t you understand?");
break;

case 5:
out.println("No chance, Lance.");

case 6:
out.println("Sure, whatever.");

case 7:
out.println("Yes, but only if you’re nice to me.");

case 8:
out.println("Yes (as if I care).");

case 9:
out.println("No, not until Cromwell seizes Dover.");

case 10:
out.println("No, not until Nell squeezes Rover.");

default:
out.print("You think you have problems?");
out.println(" My random number generator is broken!");
}

out.println("Goodbye");

keyboard.close();
}
}

I’ve put two runs of this code in Figure 11-3. In the first run, the randomNumber is 7. The program executes cases 7 through 10, and the default. In the second run, the randomNumber is 3. The program executes cases 3 and 4. Then, because case 4 has a break statement, the program jumps out of the switch and displays Goodbye.

image

FIGURE 11-3: Please make up your mind.

remember The switch statement in Listing 11-2 is missing some break statements. Even without these break statements, the code compiles with no errors. But when you run the code in Listing 11-2, you don’t get the results that you want.

Using Fall-Through to Your Advantage

Often, when you’re using a switch statement, you don’t want fall-through, so you pepper break statements throughout the switch. But, sometimes, fall-through is just the thing you need.

Take the number of days in a month. Is there a simple rule for this? Months containing the letter r have 31 days? Months in which i comes before e except after c have 30 days?

You can fiddle with if conditions all you want. But to handle all the possibilities, I prefer a switch statement. Listing 11-3 demonstrates the idea.

LISTING 11-3 Finding the Number of Days in a Month

import java.util.Scanner;

class DaysInEachMonth {

public static void main(String args[]) {

Scanner keyboard = new Scanner(System.in);
int month, numberOfDays = 0;
boolean isLeapYear;
System.out.print("Which month? ");
month = keyboard.nextInt();

switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
numberOfDays = 31;
break;

case 4:
case 6:
case 9:
case 11:
numberOfDays = 30;
break;

case 2:
System.out.print("Leap year (true/false)? ");
isLeapYear = keyboard.nextBoolean();
if (isLeapYear) {
numberOfDays = 29;
} else {
numberOfDays = 28;
}
}

System.out.print(numberOfDays);
System.out.println(" days");

keyboard.close();
}
}

Figure 11-4 shows several runs of the program in Listing 11-3. For month number 6, the computer jumps to case 6. There are no statements inside the case 6 clause, so that part of the program’s run is pretty boring.

image

FIGURE 11-4: How many days until the next big deadline?

But with no break in the case 6 clause, the computer marches right along to case 9. Once again, the computer finds no statements and no break, so the computer ventures to the next case, which is case 11. At that point, the computer hits pay dirt. The computer assigns 30 to numberOfDays and breaks out of the entire switch statement. (See Figure 11-5.)

image

FIGURE 11-5: Follow the bouncing ball.

February is the best month of all. For one thing, the February case in Listing 11-3 contains a call to the Scanner class’s nextBoolean method. The method expects me to type either true or false. The code uses whatever word I type to assign a value to a boolean variable. (In Listing 11-3, I assign true or false to the isLeapYear variable.)

February also contains its own if statement. In Chapter 10, I nest if statements within other if statements. But in February, I nest an if statement within a switch statement. That’s cool.

tryitout Here’s where you get practice using switch statements.

DON’T DO THIS AT HOME (OR ANYWHERE ELSE)

What’s wrong with the following code, and how can you fix it?

switch (amount) {
case 1:
System.out.println("US cent");
case 5:
System.out.println("US nickel");
case 10:
System.out.println("US dime");
case 25:
System.out.println("US quarter");
case 50:
System.out.println("US half dollar");
case 100:
System.out.println("US dollar");
default:
System.out.println("Not a US coin");
}

DAYS OF THE WEEK

Write a program that reads a number (from 1 to 7) and displays the day of the week corresponding to that number. For example, in the United States, Sunday is counted as the first day of the week. So, if the user types 1, my program displays Sunday. If the user types 2, my program displays Monday. And so on.

TIME TO EAT

Write a program that asks the user what the current hour is, and uses a switch statement to inform the user about mealtime. If the hour is between 6 a.m. and 9 a.m., tell the user, “Breakfast is served.” If the hour is between 11 a.m. and 1 p.m., tell the user, “Time for lunch.” If the hour is between 5 p.m. and 8 p.m., tell the user, “It’s dinnertime.” For any other hours, tell the user, “Sorry, you’ll have to wait, or go get a snack.”

A TINY CALCULATOR

Write a program that prompts the user for two numbers and a character. In a switch statement, the program applies the character’s operation to the two numbers and displays the result. A run of the program might look like this:

First number: 21.0
Second number: 8.0
Operation (+ - * or /): +
29.0

The program accepts any one of the characters +, -, *, or /. For an additional challenge, enhance the program’s output as follows:

First number: 31.0
Second number: 10.0
Operation (+ - * or /): *
31.0 * 10.0 = 310.0

Remember that you can’t use Java’s + sign to display a char value next to a numeric value. If you execute System.out.println(5 + ’ ’ + ’*’), Java doesn’t display 5 *. Instead, Java displays 79. (If you don’t believe me, try it in JShell.)

COLOR BY NUMBERS

In the RGB color model, numeric values indicate amounts of red, green, and blue. If you mix red, green, and blue to show only eight colors, 0 is black, 1 is blue, 2 is green, 3 is cyan, 4 is red, 5 is magenta, 6 is yellow, and 7 is white. Write a program that reads a number from the keyboard and displays the name of that number’s color.

Using a Conditional Operator

Java has a neat feature that I can’t resist writing about. Using this feature, you can think about alternatives in a natural way.

And what do I mean by “a natural way”? If I think out loud as I imitate the if statement near the end of Listing 11-3, I come up with this:

//The thinking in Listing 11-3:
What should I do next?
If this is a leap year,
I’ll make the numberOfDays be 29;
Otherwise,
I’ll make the numberOfDays be 28.

I’m wandering into an if statement without a clue about what I’m doing next. That seems silly. It’s February, and everybody knows what you do in February. You ask how many days the month has.

In my opinion, the code in Listing 11-3 doesn’t reflect the most natural way to think about February. Here’s a more natural way:

//A more natural way to think about the problem:
The value of numberOfDays is…
Wait! Is this a leap year?
If yes, 29
If no, 28

In this second, more natural way of thinking, I know from the start that I’m picking a number of days. So by the time I reach a fork in the road (Is this a leap year?), the only remaining task is to choose between 29 and 28.

I can make the choice with finesse:

case 2:
System.out.print("Leap year (true/false)? ");
isLeapYear = keyboard.nextBoolean();
numberOfDays = isLeapYear ? 29 : 28;

The ? : combination is called a conditional operator. In Figure 11-6, I show you how my natural thinking about February can morph into the conditional operator’s format.

image

FIGURE 11-6: From your mind to the computer’s code.

Taken as a whole, isLeapYear ? 29 : 28 is an expression with a value. And what value does this expression have? Well, the value of isLeapYear ? 29 : 28 is either 29 or 28. It depends on whether isLeapYear is or isn’t true. That’s how the conditional operator works:

  • If the stuff before the question mark is true, the whole expression’s value is whatever comes between the question mark and the colon.
  • If the stuff before the question mark is false, the whole expression’s value is whatever comes after the colon.

Figure 11-7 gives you a goofy way to visualize these ideas.

image

FIGURE 11-7: Have you ever seen an expression talking to itself?

The conditional operator’s overall effect is as though the computer is executing

numberOfDays = 29;

or

numberOfDays = 28;

One way or another, numberOfDays gets a value, and the code solves the problem with style.

tryitout Get some practice using Java’s conditional operator.

DRESSED TO THE NINES

Take another look at the Try It Out programs in Chapter 9. Rewrite some of those programs using conditional operators.

  • Ask the user if he or she wants to see a smiley face. Display :-) if the user replies Y; display :-( otherwise.
  • Randomly generate one number and have the user enter a number. Display You win! if the numbers match, and You lose otherwise.
  • Read a number of meters from the keyboard. Then read a letter (either c or m) from the keyboard. If the letter is c, convert meters to centimeters and display the result. If the letter is m, convert meters to millimeters and display the result. (Assume that the user always types either the letter c or the letter m.)
  • Read a number of meters from the keyboard. Then read a letter from the keyboard. If the letter is c, convert meters to centimeters and display the result. If the letter is m, convert meters to millimeters and display the result. For any other letters, display the original number of meters.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.22.181.47