Java Programming   Java Programming
 |Sofia Home | Content Gallery |
Home
Syllabus
Schedule
Lessons
Assignments
Resources

Lesson 5.4 Multiple Choice

Multi-way Branches

As you saw in Lesson 5.3, "Logicals", you can combine different boolean conditions using the AND and OR operators. Another way to do the same thing is through nesting. 

Nesting means that one if statement is embedded or nested in the body of another if statement. Here's an illustration that shows some simple nested logic. You can click on the illustration to enlarge it.

Image shows nested if-else statements

The embedded if statement can appear in the body of the if portion of an if-else statement, in the body of the else portion, or both. Let's look at a semi realistic example.

[We haven't yet covered iteration, so parts of the code won't be understandable to you. Because of that, I've shown psuedocode comments for portions of the code.]

Counting Words

Suppose you had a sentence inside a TextField, and you wanted to count how many words were in the sentence. For now, just assume that every sentence is separated by one or more spaces. Don't worry about TAB characters, newline characters, periods, or other punctuation.

First, you would retrieve the text from the TextField, and store it in a String, by sending your TextField the getText() message. Then, using a loop [which you'll study in the next lesson], you could easily examine all of the characters in the String.

Back to Top

Separator or Not

To find out how many words are in your sentence is a little complex. Here's how to do it.
  1. Create an int counter to hold the number of words in the sentence, and initialize it to zero.
  2. Next, assume that when you start examining the characters in the String, that you are not yet inside a word. Represent this assumption using a boolean variable, inAWord.
  3. Examine each character in the String in turn. [This is the portion that requires a loop.] As you look at each character, classify it as either a character which is part of a word, or a character that separates words. For now, remember, you can assume that every word is separated only by spaces.

At this point, your code should look something like this:

Word Counting 1
int numWords = 0;
boolean inAWord = false;
String sentence = myTF.getText();

// Examine each character in turn
// Store each character in the char ch

if (ch == ' ') // It is a space
{
  // Handle spaces
}
else
{
  // It is part of a word
}

Once you've classified each character, you have to decide what to do with it. 

Back to Top

In A Word or Not

Suppose that the character you just looked at was not a space. That means that you are now inside a word. As a result:
  1. If the previous character you had examined was a space, then you should update your count of words, and set inAWord to true.
  2. If the previous character you looked at was not a space, then you've examined another character in a word which you've already counted.
Since the inAWord variable represents your state [whether you are currently inside a word or not], you can use a nested if statement to take action when this occurs. 

Here's what your code should look like now:
Counting Words 2
int numWords = 0;
boolean inAWord = false;
String sentence = myTF.getText();

// Examine each character in turn
// Store each character in the char ch

if (ch == ' ') // It is a space
{
  // Handle spaces
}
else
{
  // It is part of a word
  if (inAWord)
  {
    // Do nothing; already counted word
  }
  else // Starting a new word; count it
  {
    numWords++;
    inAWord = true;
  }
}

Back to Top

Resetting Your Flag

As shown, your code will correctly count when you enter the first word, but unless you reset the inAWord flag when you leave the word you're examining, your counter will never get past one.

How do you reset your counter? That's right! Another nested if statement. Here's the logic.

If the character you just examined was a space then:

  1. If you were previously inside a word [if inAWord was true], then you have just left the current word, and so you must reset the value of the inAWord variable to false.
  2. If you were not previously inside a word [if inAWord wasfalse], then you've just examined the next of several spaces, so you don't have to do anything.

Here's what your code should look like after adding the second nested if statement:

Counting Words 2
int numWords = 0;
boolean inAWord = false;
String sentence = myTF.getText();

// Examine each character in turn
// Store each character in the char ch

if (ch == ' ') // It is a space
{
  // Handle spaces
  if (inAWord) // Leaving word; reset
  {
    inAWord = false;
  }
  else
  {
    // Just another space; do nothing
  }
}
else
{
  // It is part of a word
  if (inAWord)
  {
    // Do nothing; already counted word
  }
  else // Starting a new word; count it
  {
    numWords++;
    inAWord = true;
  }
}

Once you've processed all of the characters in your sentence, numWords will contain the number of words in the sentence. Here's an applet, CountWords.java that uses this logic to count the number of words you type into its TextField.

CountWords uses loops, as was mentioned earlier, as well as two other features you'll study in this lesson: the Java 1.0 action() method and the BorderLayout layout manager.

Back to Top

Chutes 'n' Ladders

CountWords.java is fairly straightforward, but it contains only a single level of nesting. What would you do, for instance, if you needed to discover which of four different Button objects triggered an ActionEvent

To handle this situation, you'd need to have multiple levels of nesting, so your code would look something like this:
Nested if Statements
public void
actionPerformed(ActionEvent e)
{
  Object clicked = e.getSource();

  if (clicked == btnOne)
  {
    // Handle btnOne click here
  }
  else
  {
    if (clicked == btnTwo)
    {
      // Handle btnTwo click
    }
    else
    {
      if (clicked == btnThree)
      {
        // Handle btnThree click
      }
      else
      {
        // Handle btnFour click
      }
    }
  }
}

Back to Top

Ladder-Style

Unfortunately, deeply nested logic like this can be very hard to read and understand. There is, however, a simple solution. 

Rather than using nested style if statements, you can format your code so that the else portion is immediately followed by another if. The actual logic is the same, but this "ladder-style" if-else-if is much easier to read.

Look at the code shown here and see if you don't agree:
Ladder-style if-else-if Statements
public void
actionPerformed(ActionEvent e)
{
  Object clicked = e.getSource();

  if (clicked == btnOne)
  {
    // Handle btnOne click here
  }
  else if (clicked == btnTwo)
  {
    // Handle btnTwo click
  }
  else if (clicked == btnThree)
  {
    // Handle btnThree click
  }
  else
  {
    // Handle btnFour click
  }
}

Back to Top

Multiple Choice

As you can see, nested if statements, as well as the ladder-style if-else-if statements, provide you with the ability to do multi-way branches.

Another Java facility, the switch statement, provides an even more efficient way to select between several different alternatives, provided you can live with its limitations and somewhat idiosyncratic behavior.

Many other languages have a multi-way branch statement, usually called a case statement. If you've programmed in one of these different languages, you might find the term switch a little unusual. The name seems much more logical, however, if you think of a railway switching yard or a telephone switchboard, rather than a light-switch.

The switch statement is different than the if-else statement because the switch is based upon integer evaluation, rather than upon a boolean test. 

Let's briefly look at the syntax of the switch statement, then we'll take a look at how it works.

Switch Syntax

Here's an illustration that shows the syntax of the switch statement. [Click the illustration to enlarge] As you can see, the switch statement consists of five different parts.

Image illustrates the syntax of the switch statement. Click to enlarge image.

  1. The switch keyword, followed by an integer expression enclosed in parentheses. The body of the switch statement, which follows, is enclosed in braces.
  2. Any number of case labels. Each case label consists of the keyword case, followed by a constant numeric expression. The case label ends with a colon.
  3. Any number of statements following each case label.
  4. A break statement to end each case.
  5. A default statement to handle the unmatched cases.
Back to Top

How it works

When a switch statement is encountered, the first thing that happens is that its integer expression is evaluated. After the test expression is evaluated the following steps are performed:
  1. The list of labeled constants is scanned, looking for a match. If an exact match is found: 
    • Java begins executing the first line of code immediately following the matching case label.
    • Each line of code following the case label is executed sequentially until either a break statement is encountered or all of the statements in the switch body have been executed.
  2. If no match is found, then execution jumps to the statement following the default keyword, if a default case was supplied.
  3. If no match was found and there was no default case, then execution jumps to the first statement following the switch body.

A Simple Example

A common use for a switch statement is to implement a menu. Let's create a simple menu that allows the user to select 1) for Twinkies, and 2) for Tofu. Something for everyone.

As with the other examples in this lesson, we'll build the user interface using the TextField class and listen for events by using the Java 1.0 action() method. When the user presses ENTER inside the TextField, we'll grab the first character from the text entered and use that as the selection value for our switch statement.

[The switch statement can evaluate int, long, byte, short, or char selection values. It will not work with double, long, String, or any object types.]

Here's the code for the evaluation portion of SimpleMenu.java.
Using the switch Statement
switch (ch)
{
  case '1':
    aLbl.setText("Here's TOFU");
    break;
  case '2':
    aLbl.setText("Here's TWINKIE");
    break;
  default:
    aLbl.setText("Unknown Choice");
}

You can try out the program here. Enter some nonsense phrases as well as testing the values 1 and 2.

Back to Top

Switch Pitfalls

There are two common problems students encounter when learning to use the switch statement. 

The first problem has to do with the case labels. Each case label must include:

  • A constant integral expression followed by a colon.
  • This means you can't use variables, Strings or ranges as part of your case label.
The second problem has to do with forgetting to use a break statement. If you don't include a break statement, then all of the statements in the switch body, following your case are executed as well.

Something to Talk About

Here's a simple experiment. Download, compile and run the file SimpleMenu.java. When you are done, make the following changes:
  1. Remove the break statements in the switch body and test it by entering 1, 2, and 3. What happens?
  2. Change the switch statement to use a multi-way, ladder-style if-else-if structure. Now what happens if you enter 1, 2, and 3?

Please continue to the next section of this lesson.

 

Back to Top

 

Content Developed by Stephen Gilbert, Licensed under a Creative Commons License
Published by the Sofia Open Content Initiative
© 2004 Foothill-De Anza Community College District &The William and Flora Hewlett Foundation