Chapter 5
Controlling Program Flow with Decision-Making Statements
In This Chapter
Writing statements that choose between alternatives
Putting statements inside one another
Choosing among many alternatives
The TV show Dennis the Menace aired on CBS from 1959 to 1963. I remember one episode in which Mr. Wilson was having trouble making an important decision. I think it was something about changing jobs or moving to a new town. Anyway, I can still see that shot of Mr. Wilson sitting in his yard, sipping lemonade, and staring into nowhere for the whole afternoon. Of course, the annoying character Dennis was constantly interrupting Mr. Wilson’s peace and quiet. That’s what made this situation funny.
What impressed me about this episode (the reason why I remember it so clearly even now) was Mr. Wilson’s dogged intent in making the decision. This guy wasn’t going about his everyday business, roaming around the neighborhood, while thoughts about the decision wandered in and out of his mind. He was sitting quietly in his yard, making marks carefully and logically on his mental balance sheet. How many people actually make decisions this way?
At that time, I was still pretty young. I’d never faced the responsibility of having to make a big decision that affected my family and me. But I wondered what such a decision-making process would be like. Would it help to sit there like a stump for hours on end? Would I make my decisions by the careful weighing and tallying of options? Or would I shoot in the dark, take risks, and act on impulse? Only time would tell.
Making Decisions (Java if Statements)
When you’re writing computer programs, you’re constantly hitting forks in roads. Did the user correctly type his or her password? If yes, let the user work; if no, kick the bum out. So the Java programming language needs a way of making a program branch in one of two directions. Fortunately, the language has a way. It’s called an if
statement.
Guess the number
Listing 5-1 illustrates the use of an if
statement. Two runs of the program in Listing 5-1 are shown in Figure 5-1.
Listing 5-1: A Guessing Game
import static java.lang.System.out;
import java.util.Scanner;
import java.util.Random;
class GuessingGame {
public static void main(String args[]) {
Scanner keyboard = new Scanner(System.in);
out.print(“Enter an int from 1 to 10: “);
int inputNumber = keyboard.nextInt();
int randomNumber = new Random().nextInt(10) + 1;
if (inputNumber == randomNumber) {
out.println(“**********”);
out.println(“*You win.*”);
out.println(“**********”);
} else {
out.println(“You lose.”);
out.print(“The random number was “);
out.println(randomNumber + “.”);
}
out.println(“Thank you for playing.”);
}
}
The program in Listing 5-1 plays a guessing game with the user. The program gets a number (a guess) from the user and then generates a random number between 1 and 10. If the number that the user entered is the same as the random number, the user wins. Otherwise, the user loses, and the program tells the user what the random number was.
She controlled keystrokes from the keyboard
Taken together, the lines
import java.util.Scanner;
Scanner keyboard = new Scanner(System.in);
int inputNumber = keyboard.nextInt();
in Listing 5-1 get whatever number the user types on the computer’s keyboard. The last of the three lines puts this number into a variable named inputNumber. If these lines look complicated, don’t worry. You can copy these lines almost word for word whenever you want to read from the keyboard. Include the first two lines (the import
and Scanner
lines) just once in your program. Later in your program, wherever the user types an int
value, include a line with a call to nextInt
(as in the last of the preceding three lines of code).
Of all the names in these three lines of code, the only two names that I coined myself are inputNumber and keyboard. All the other names are part of Java. So, if I want to be creative, I can write the lines this way:
import java.util.Scanner;
Scanner
readingThingie
= new Scanner(System.in);
int
valueTypedIn
= readingThingie
.nextInt();
I can also beef up my program’s import declarations, as I do in Listings 5-2 and 5-3. Other than that, I have very little leeway.
As you read on in this book, you’ll start recognizing the patterns behind these three lines of code, so I don’t clutter up this section with all the details. For now, you can just copy these three lines and keep the following in mind:
When you import java.util.Scanner
, you don’t use the word static.
But importing Scanner
is different from importing System.out
. When you import java.lang.System.out
, you use the word static. (See Listing 5-1.) The difference creeps into the code because Scanner
is the name of a class, and System.out
isn’t the name of a class.
For a quick look at the use of the word static in import declarations, see one of the sidebars in Chapter 4. For a more complete story about the word, see Chapter 10.
The name System.in stands for the keyboard.
To get characters from some place other than the keyboard, you can type something other than System.in
inside the parentheses.
What else can you put inside the parentheses? For some ideas, see Chapter 8.
In Listing 5-1, I make the arbitrary decision to give one of my variables the name keyboard
. The name keyboard
reminds you, the reader, that this variable refers to a bunch of plastic buttons in front of your computer. Naming something keyboard
doesn’t tell Java anything about plastic buttons or about user input. On the other hand, the name System.in
always tells Java about those plastic buttons. The code Scanner keyboard = new Scanner(System.in)
in Listing 5-1 connects the name keyboard
with the plastic buttons that we all know and love.
When you expect the user to type an int
value (a whole number of some kind), use nextInt()
.
If you expect the user to type a double
value (a number containing a decimal point), use nextDouble()
. If you expect the user to type true or false, use nextBoolean()
. If you expect the user to type a word like Barry, Java, or Hello, use next()
.
For an example in which the user types a word, see Listing 5-3. For an example in which the user types a single character, see Listing 6-4 in Chapter 6. For an example in which a program reads an entire line of text (all in one big gulp), see Chapter 8.
You can get several values from the keyboard, one after another.
To do this, use the keyboard.nextInt()
code several times.
To see a program that reads more than one value from the keyboard, go to Listing 5-4.
Creating randomness
Achieving real randomness is surprisingly difficult. Mathematician Persi Diaconis says that if you flip a coin several times, always starting with the head side up, you’re likely to toss heads more often than tails. If you toss several more times, always starting with the tail side up, you’re likely to toss tails more often than heads. In other words, coin tossing isn’t really fair.*
Computers aren’t much better than coins and human thumbs. A computer mimics the generation of random sequences but, in the end, the computer just does what it’s told and does all this in a purely deterministic fashion. So in Listing 5-1, when the computer executes
import java.util.Random;
int randomNumber = new Random().nextInt(10) + 1;
the computer appears to give us a randomly generated number — a whole number between 1 and 10. But it’s all a fake. The computer just follows instructions. It’s not really random, but without bending a computer over backwards, it’s the best that anyone can do.
Once again, I ask you to take this code on blind faith. Don’t worry about what new Random().nextInt
means until you have more experience with Java. Just copy this code into your own programs and have fun with it. And if the numbers from 1 to 10 aren’t in your flight plans, don’t fret. To roll an imaginary die, write the statement
int rollEmBaby = new Random().nextInt(
6
) + 1;
With the execution of this statement, the variable rollEmBaby
gets a value from 1
to 6
.
The if statement
At the core of Listing 5-1 is a Java if
statement. This if
statement represents a fork in the road. (See Figure 5-2.) The computer follows one of two prongs — the prong that prints You win
or the prong that prints You lose
. The computer decides which prong to take by testing the truth or falsehood of a condition. In Listing 5-1, the condition being tested is
inputNumber == randomNumber
Does the value of inputNumber
equal the value of randomNumber
? When the condition is true, the computer does the stuff between the condition and the word else. When the condition turns out to be false, the computer does the stuff after the word else. Either way, the computer goes on to execute the last println
call, which displays Thank you for playing.
The double equal sign
In Listing 5-1, in the if
statement’s condition, notice the use of the double equal sign. Comparing two numbers to see whether they’re the same isn’t the same as setting something equal to something else. That’s why the symbol to compare for equality isn’t the same as the symbol that’s used in an assignment or an initialization. In an if
statement’s condition, you can’t replace the double equal sign with a single equal sign. If you do, your program just won’t work. (You almost always get an error message when you try to compile your code.)
On the other hand, if you never make the mistake of using a single equal sign in a condition, you’re not normal. Not long ago, while I was teaching an introductory Java course, I promised that I’d swallow my laser pointer if no one made the single equal sign mistake during any of the lab sessions. This wasn’t an idle promise. I knew I’d never have to keep it. As it turned out, even if I had ignored the first ten times anybody made the single equal sign mistake during those lab sessions, I would still be laser-pointer free. Everybody mistakenly uses the single equal sign several times in his or her programming career. The trick is not to avoid making the mistake; the trick is to catch the mistake whenever you make it.
Brace yourself
The if
statement in Listing 5-1 has two halves — a top half and a bottom half. I have names for these two parts of an if
statement. I call them the if part (the top half) and the else part (the bottom half).
The if
part in Listing 5-1 seems to have more than one statement in it. I make this happen by enclosing the three statements of the if
part in a pair of curly braces. When I do this, I form a block. A block is a bunch of statements scrunched together by a pair of curly braces.
With this block, three calls to println
are tucked away safely inside the if
part. With the curly braces, the rows of asterisks and the words You win
display only when the user’s guess is correct.
This business with blocks and curly braces applies to the else
part as well. In Listing 5-1, whenever inputNumber
doesn’t equal randomNumber
, the computer executes three print
/println
calls. To convince the computer that all three of these calls are inside the else
clause, I put these calls into a block. That is, I enclose these three calls in a pair of curly braces.
Indenting if statements in your code
Notice how, in Listing 5-1, the print
and println
calls inside the if
statement are indented. (This includes both the You win
and You lose
statements. The print
and println
calls that come after the word else are still part of the if
statement.) Strictly speaking, you don’t have to indent the statements that are inside an if
statement. For all the compiler cares, you can write your whole program on a single line or place all your statements in an artful, misshapen zigzag. The problem is that neither you nor anyone else can make sense of your code if you don’t indent your statements in some logical fashion. In Listing 5-1, the indenting of the print
and println
statements helps your eye (and brain) see quickly that these statements are subordinate to the overall if
/else
flow.
In a small program, unindented or poorly indented code is barely tolerable. But in a complicated program, indentation that doesn’t follow a neat, logical pattern is a big, ugly nightmare.
Elseless in Ifrica
Okay, so the title of this section is contrived. Big deal! The idea is that you can create an if
statement without the else
part. Take, for instance, the code in Listing 5-1. Maybe you’d rather not rub it in whenever the user loses the game. The modified code in Listing 5-2 shows you how to do this (and Figure 5-3 shows you the result).
Listing 5-2: A Kinder, Gentler Guessing Game
import static java.lang.System.in;
import static java.lang.System.out;
import java.util.Scanner;
import java.util.Random;
class DontTellThemTheyLost {
public static void main(String args[]) {
Scanner keyboard = new Scanner(in);
out.print(“Enter an int from 1 to 10: “);
int inputNumber = keyboard.nextInt();
int randomNumber = new Random().nextInt(10) + 1;
if (inputNumber == randomNumber) {
out.println(“*You win.*”);
}
out.println(“That was a very good guess :-)”);
out.print(“The random number was “);
out.println(randomNumber + “.”);
out.println(“Thank you for playing.”);
}
}
The if
statement in Listing 5-2 has no else
part. When inputNumber
is the same as randomNumber
, the computer prints You win.
When inputNumber
is different from randomNumber
, the computer doesn’t print You win.
Listing 5-2 illustrates another new idea. With an import
declaration for System.in
, I can reduce new Scanner(System.in)
to the shorter new Scanner(in)
. Adding this import
declaration is hardly worth the effort. In fact, I do more typing with the import
declaration than without it. Nevertheless, the code in Listing 5-2 demonstrates that it’s possible to import System.in
.
Forming Conditions with Comparisons and Logical Operators
The Java programming language has plenty of little squiggles and doodads for your various condition-forming needs. This section tells you all about them.
Comparing numbers; comparing characters
Table 5-1 shows you the operators that you can use to compare one thing with another.
Table 5-1 Comparison Operators
Operator Symbol |
Meaning |
Example |
== |
is equal to |
|
|
is not equal to |
|
|
is less than |
|
|
is greater than |
|
|
is less than or equal to |
|
|
is greater than or equal to |
|
You can use all Java’s comparison operators to compare numbers and characters. When you compare numbers, things go pretty much the way you think they should go. But when you compare characters, things are a little strange. Comparing uppercase letters with one another is no problem. Because the letter B comes alphabetically before H, the condition ‘B’ < ‘H’
is true. Comparing lowercase letters with one another is also okay. What’s strange is that when you compare an uppercase letter with a lowercase letter, the uppercase letter is always smaller. So, even though ‘Z’ < ‘A’
is false, ‘Z’ < ‘a’
is true.
Comparing objects
When you start working with objects, you find that you can use ==
and !=
to compare objects with one another. For instance, a button that you see on the computer screen is an object. You can ask whether the thing that was just mouse-clicked is a particular button on your screen. You do this with Java’s equality operator.
if (e.getSource() == bCopy) {
clipboard.setText(which.getText());
The big gotcha with Java’s comparison scheme comes when you compare two strings. (For a word or two about Java’s String
type, see the section about reference types in Chapter 4.) When you compare two strings with one another, you don’t want to use the double equal sign. Using the double equal sign would ask, “Is this string stored in exactly the same place in memory as that other string?” Usually, that’s not what you want to ask. Instead, you usually want to ask, “Does this string have the same characters in it as that other string?” To ask the second question (the more appropriate question) Java’s String
type has a method named equals. (Like everything else in the known universe, this equals
method is defined in the Java API, short for Application Programming Interface.) The equals
method compares two strings to see whether they have the same characters in them. For an example using Java’s equals
method, see Listing 5-3. (Figure 5-4 shows a run of the program in Listing 5-3.)
Listing 5-3: Checking a Password
import static java.lang.System.*;
import java.util.Scanner;
class CheckPassword {
public static void main(String args[]) {
out.print(“What’s the password? “);
Scanner keyboard = new Scanner(in);
String password = keyboard.next();
out.println(“You typed >>” + password + “<<”);
out.println();
if (password == “swordfish”) {
out.println(“The word you typed is stored”);
out.println(“in the same place as the real”);
out.println(“password. You must be a”);
out.println(“hacker.”);
} else {
out.println(“The word you typed is not”);
out.println(“stored in the same place as”);
out.println(“the real password, but that’s”);
out.println(“no big deal.”);
}
out.println();
if (password.equals(“swordfish”)) {
out.println(“The word you typed has the”);
out.println(“same characters as the real”);
out.println(“password. You can use our”);
out.println(“precious system.”);
} else {
out.println(“The word you typed doesn’t”);
out.println(“have the same characters as”);
out.println(“the real password. You can’t”);
out.println(“use our precious system.”);
}
}
}
In Listing 5-3, the call keyboard.next()
grabs whatever word the user types on the computer keyboard. The code shoves this word into the variable named password. Then the program’s if
statements use two different techniques to compare password
with “swordfish”
.
The more appropriate of the two techniques uses Java’s equals
method. The equals
method looks funny because when you call it, you put a dot after one string and put the other string in parentheses. But that’s the way you have to do it.
In calling Java’s equals
method, it doesn’t matter which string gets the dot and which gets the parentheses. For instance, in Listing 5-3, you could have written
if (“swordfish”.equals(password))
The method would work just as well.
Importing everything in one fell swoop
The first line of Listing 5-3 illustrates a lazy way of importing both System.out
and System.in
. To import everything that System
has to offer, you use the asterisk wildcard character (*
). In fact, importing java.lang.System.*
is like having about 30 separate import
declarations, including System.in
, System.out
, System.err
, System.nanoTime
, and many other System
things.
The use of an asterisk in an import
declaration is generally considered bad programming practice, so I don’t do it often in this book’s examples. But for larger programs — programs that use dozens of names from the Java API — the lazy asterisk trick is handy.
Java’s logical operators
Mr. Spock would be pleased. Java has all the operators that you need for mixing and matching logical tests. The operators are shown in Table 5-2.
Table 5-2 Logical Operators
Operator Symbol |
Meaning |
Example |
|
and |
|
|
or |
|
|
not |
|
You can use these operators to form all kinds of elaborate conditions. Listing 5-4 has an example.
Listing 5-4: Checking Username and Password
import javax.swing.JOptionPane;
class Authenticator {
public static void main(String args[]) {
String username =
JOptionPane.showInputDialog(“Username:”);
String password =
JOptionPane.showInputDialog(“Password:”);
if (
username != null &&
password != null &&
(
(username.equals(“bburd”) &&
password.equals(“swordfish”)) ||
(username.equals(“hritter”) &&
password.equals(“preakston”))
)
)
{
JOptionPane.showMessageDialog
(null, “You’re in.”);
} else {
JOptionPane.showMessageDialog
(null, “You’re suspicious.”);
}
}
}
Several runs of the program of Listing 5-4 are shown in Figure 5-5. When the username is bburd and the password is swordfish or when the username is hritter and the password is preakston, the user gets a nice message. Otherwise, the user is a bum who gets the nasty message that he or she deserves.
Listing 5-4 illustrates a new way to get user input; namely, to show the user an input dialog. The statement
String password =
JOptionPane.showInputDialog(“Password:”);
in Listing 5-4 performs more or less the same task as the statement
String password = keyboard.next();
from Listing 5-3. The big difference is, while keyboard.next()
displays dull-looking text in a console, JOptionPane.showInputDialog(“Username:”)
displays a fancy dialog box containing a text field and buttons. (Compare Figures 5-4 and 5-5.) When the user clicks OK, the computer takes whatever text is in the text field and hands that text over to a variable. In fact, Listing 5-4 uses JOptionPane.showInputDialog
twice — once to get a value for the username
variable, and a second time to get a value for the password
variable.
Near the end of Listing 5-4, I use a slight variation on the JOptionPane
business,
JOptionPane.showMessageDialog
(null, “You’re in.”);
With showMessageDialog
, I show a very simple dialog box — a box with no text field. (Again, see Figure 5-5.)
Like thousands of other names, the name JOptionPane
is defined in Java’s API. (To be more specific, JOptionPane
is defined inside something called javax.swing
, which in turn is defined inside Java’s API.) So to use the name JOptionPane
throughout Listing 5-4, I import javax.swing.JOptionPane
at the top of the listing.
Vive les nuls!
The French translations of For Dummies books are books Pour les Nuls. So a “dummy” in English is a “nul” in French. But in Java, the word null
means “nothing.” When you see
if (
username != null
in Listing 5-4, you can imagine that you see
if (
username
isn’t nothing
or
if (
username
has any value at all
To find out how username
can have no value, see the last row in Figure 5-5. When you click Cancel in the first dialog box, the computer hands null
to your program. So in Listing 5-4, the variable username
becomes null
. The comparisons username != null
checks to make sure that you haven’t clicked Cancel in the program’s first dialog box. The comparison password != null
performs the same kind of check for the program’s second dialog box. When you see the if
statement in Listing 5-4, you can imagine that you see the following:
if (
you didn’t press Cancel in the username dialog and
you didn’t press Cancel in the password dialog and
(
(
you typed
“bburd” in the
username dialog
) and
you typed
“swordfish” in the
password dialog
)) or
(
you typed
“hritter” in the
username dialog
) and
you typed
“preakston” in the
password dialog
))
)
)
(Conditions in parentheses)
Keep an eye on those parentheses! When you’re combining conditions with logical operators, it’s better to waste typing effort and add unneeded parentheses than to goof up your result by using too few parentheses. Take, for example, the expression
2 < 5 || 100 < 6 && 27 < 1
By misreading this expression, you might conclude that the expression is false. That is, you could wrongly read the expression as meaning (
something-or-other
) && 27 < 1
. Because 27 < 1 is false, you would conclude that the whole expression is false. The fact is that, in Java, any &&
operator is evaluated before any ||
operator. So the expression really asks if 2 < 5 || (
something-or-other
)
. Because 2 < 5 is true, the whole expression is true.
To change the expression’s value from true
to false
, you can put the expression’s first two comparisons in parentheses, like this:
(2 < 5 || 100 < 6) && 27 < 1
In Listing 5-4, the if
statement’s condition has more than a dozen parentheses. What happens if you omit two of them?
if (
username != null &&
password != null &&
// open parenthesis omitted
(username.equals(“bburd”) &&
password.equals(“swordfish”)) ||
(username.equals(“hritter”) &&
password.equals(“preakston”))
// close parenthesis omitted
)
Java tries to interpret your wishes by grouping everything before the “or” (the ||
operator):
if (
username != null &&
password != null &&
(username.equals(“bburd”) &&
password.equals(“swordfish”))
||
(username.equals(“hritter”) &&
password.equals(“preakston”))
)
When the user clicks Cancel and username
is null
, Java says, “Okay! The stuff before the ||
operator is false, but maybe the stuff after the ||
operator is true. I’ll check the stuff after the ||
operator to find out if it’s true.” (Java often talks to itself. The psychiatrists are monitoring this situation.)
Anyway, when Java finally checks username.equals(“hritter”)
, your program aborts with an ugly NullPointerException
message. You’ve made Java angry by trying to apply .equals
to a null username
. (Psychiatrists have recommended anger management sessions for Java, but Java’s insurance plan refuses to pay for the sessions.)
Building a Nest
Have you seen those cute Russian Matryoshka nesting dolls? Open up one, and another one is inside. Open up the second, and a third one is inside it. You can do the same thing with Java’s if
statements. (Talk about fun!) Listing 5-5 shows you how.
Listing 5-5: Nested if Statements
import static java.lang.System.out;
import java.util.Scanner;
class Authenticator2 {
public static void main(String args[]) {
Scanner keyboard = new Scanner(System.in);
out.print(“Username: “);
String username = keyboard.next();
if (username.equals(“bburd”)) {
out.print(“Password: “);
String password = keyboard.next();
if (password.equals(“swordfish”)) {
out.println(“You’re in.”);
} else {
out.println(“Incorrect password”);
}
} else {
out.println(“Unknown user”);
}
}
}
Figure 5-6 shows several runs of the code in Listing 5-5. The main idea is that to log on, you have to pass two tests. (In other words, two conditions must be true.) The first condition tests for a valid username; the second condition tests for the correct password. If you pass the first test (the username test), you march right into another if
statement that performs a second test (the password test). If you fail the first test, you never make it to the second test. Figure 5-7 shows the overall plan.
Choosing among Many Alternatives (Java switch Statements)
I’m the first to admit that I hate making decisions. If things go wrong, I would rather have the problem be someone else’s fault. Writing the previous sections (on making decisions with Java’s if
statement) knocked the stuffing right out of me. That’s why my mind boggles as I begin this section on choosing among many alternatives. What a relief it is to have that confession out of the way!
Your basic switch statement
Now, it’s time to explore situations in which you have a decision with many branches. Take, for instance, the popular campfire song “Al’s All Wet.” (For a review of the lyrics, see the sidebar.) You’re eager to write code that prints this song’s lyrics. Fortunately, you don’t have to type all the words over and over again. Instead, you can take advantage of the repetition in the lyrics.
A complete program to display the “Al’s All Wet” lyrics won’t come until Chapter 6. In the meantime, assume that you have a variable named verse. The value of verse
is 1
, 2
, 3
, or 4
, depending on which verse of “Al’s All Wet” you’re trying to print. You could have a big, clumsy bunch of if
statements that checks each possible verse
number.
if (verse == 1) {
out.println(“That’s because he has no brain.”);
}
if (verse == 2) {
out.println(“That’s because he is a pain.”);
}
if (verse == 3) {
out.println(“’Cause this is the last refrain.”);
}
But that approach seems wasteful. Why not create a statement that checks the value of verse
just once and then takes an action based on the value that it finds? Fortunately, just such a statement exists. It’s called a switch
statement. Listing 5-6 has an example of a switch
statement.
Listing 5-6: A switch Statement
import static java.lang.System.out;
import java.util.Scanner;
class JustSwitchIt {
public static void main(String args[]) {
Scanner keyboard = new Scanner(System.in);
out.print(“Which verse? “);
int verse = keyboard.nextInt();
switch (verse) {
case 1:
out.println(“That’s because he has no brain.”);
break;
case 2:
out.println(“That’s because he is a pain.”);
break;
case 3:
out.println(“’Cause this is the last refrain.”);
break;
default:
out.println(“No such verse. Please try again.”);
break;
}
out.println(“Ohhhhhhhh. . . .”);
}
}
Figure 5-8 shows two runs of the program in Listing 5-6. (Figure 5-9 illustrates the program’s overall idea.) First, the user types a number, like the number 2. Then, execution of the program reaches the top of the switch
statement. The computer checks the value of the verse
variable. When the computer determines that the verse
variable’s value is 2
, the computer checks each case of the switch
statement. The value 2
doesn’t match the topmost case, so the computer proceeds on to the middle of the three cases. The value posted for the middle case (the number 2) matches the value of the verse
variable, so the computer executes the statements that come immediately after case 2. These two statements are
out.println(“That’s because he is a pain.”);
break;
The first of the two statements displays the line That’s because he is a pain.
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 5-6, the computer skips right past the case that would display ’Cause this is the last refrain.
In fact, the computer jumps out of the entire switch
statement and goes straight to the statement just after the end of the switch
statement. The computer displays Ohhhhhhhh. . . .
because that’s what the statement after the switch
statement tells the computer to do.
If the pesky user asks for verse 6, the computer responds by dropping past cases 1, 2, and 3. Instead, the computer does the default. In the default, the computer displays No such verse. Please try again
, and then breaks out of the switch
statement. After the computer is out of the switch
statement, the computer displays Ohhhhhhhh. . . .
To break or not to break
In every Java programmer’s life, a time comes when he or she 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.
Usually, when you’re using a switch
statement, you don’t want fall-through, so you pepper break
statements throughout the switch
statements. But, occasionally, fall-through is just the thing you need. Take, for instance, the “Al’s All Wet” song. (The classy lyrics are shown in the sidebar bearing the song’s name.) Each verse of “Al’s All Wet” adds new lines in addition to the lines from previous verses. This situation (accumulating lines from one verse to another) cries out for a switch
statement with fall-through. Listing 5-7 demonstrates the idea.
Listing 5-7: A switch Statement with Fall-Through
import static java.lang.System.out;
import java.util.Scanner;
class FallingForYou {
public static void main(String args[]) {
Scanner keyboard = new Scanner(System.in);
out.print(“Which verse? “);
int verse = keyboard.nextInt();
switch (verse) {
case 3:
out.print(“Last refrain, “);
out.println(“last refrain,”);
case 2:
out.print(“He’s a pain, “);
out.println(“he’s a pain,”);
case 1:
out.print(“Has no brain, “);
out.println(“has no brain,”);
}
out.println(“In the rain, in the rain.”);
out.println(“Ohhhhhhhh...”);
out.println();
}
}
Figure 5-10 shows several runs of the program in Listing 5-7. Because the switch has no break
statements in it, fall-through happens all over the place. For instance, when the user selects verse 2, the computer executes the two statements in case 2:
out.print(“He’s a pain, “);
out.println(“he’s a pain,”);
Then, the computer marches right on to execute the two statements in case 1:
out.print(“Has no brain, “);
out.println(“has no brain,”);
That’s good, because the song’s second verse has all these lines in it.
Notice what happens when the user asks for verse 6. The switch
statement in Listing 5-7 has no case 6 and no default, so none of the actions inside the switch
statement are executed. Even so, with statements that print In the rain, in the rain
and Ohhhhhhhh. . .
right after the switch
statement, the computer displays something when the user asks for verse 6.
Along comes Java 7
In Listings 5-6 and 5-7, the variable verse
(an int
value) steers the switch
statement to one case or another. An int
value inside a switch
statement works in any version of Java, old or new. (For that matter, char
values and a few other kinds of values have worked in Java’s switch
statements ever since Java was a brand new language.)
But if you live in the fast lane and you’re using Java 7, you can set it up so that the case to be executed in a switch
statement depends on the value of a particular string. Listing 5-8 illustrates the use of strings in switch
statements. Figure 5-11 shows a run of the code in Listing 5-8.
Listing 5-8: A switch Statement with a String
import static java.lang.System.out;
import java.util.Scanner;
class SwitchIt7 {
public static void main(String args[]) {
Scanner keyboard = new Scanner(System.in);
out.print(“Which verse (one, two or three)? “);
String verse = keyboard.next();
switch (
verse
) {
case
“one”
:
out.println(“That’s because he has no brain.”);
break;
case
“two”
:
out.println(“That’s because he is a pain.”);
break;
case
“three”
:
out.println(“’Cause this is the last refrain.”);
break;
default:
out.println(“No such verse. Please try again.”);
break;
}
out.println(“Ohhhhhhhh. . . .”);
}
}