Chapter 5: Conditionals and Loops


The previous chapter showed you how method calls can be used to detour the flow of program execution. This chapter will introduce two more ways to vary program flow: conditionals and loops. By the end of this chapter, you will be able to write programs in which control flows in quite intricate patterns.

Conditionals

If a method call is like a detour in the path of execution, then a conditional is like a fork in the road. Conditional code is executed only if a certain criterion is met, typically when a certain boolean expression evaluates to true.

We will begin with the if statement, which is Java's most basic conditional. We will also look at the more complicated ternary operator and switch statement.

if

In its simplest form, the if statement looks like this:

if (boolean_expression)     do_something; 

The code immediately following the if keyword must be of boolean type and must be enclosed in parentheses. The code that follows the parenthetical boolean expression can be either a single statement or a block of statements enclosed in curly brackets. Let's look at some examples.

The following code fragment prints out a message if x is divisible by 10:

if (x%10 == 0)   System.out.println("x is divisible by 10.");

In the next example, y and z are both reduced if their product exceeds 1,000:

if (y*z > 1000) {   y -= 10;   z -= 20; }

Note in the previous example that if the condition is met, the action to be taken consists of two statements. When the conditional action is longer than a single statement, the multiple statements of the action are enclosed in curly brackets.

if and else

An if statement can be enhanced with the else keyword. You can only use else after the statement or curly bracket-enclosed block that follows an if. As with if, the code that follows else can be either a single statement or a block of statements within curly brackets. As you might expect, the code following else is executed if the if statement's boolean expression evaluates to false.

For example, the following code prints out a message that depends on whether the value of x is even or odd:

if (x%2 == 0)   System.out.println(x + " is even."); else   System.out.println(x + " is odd.");

In the next example, the method "clamps" the value of its z argument. The return value is z, unless z exceeds a lower or upper limit. If this is the case, the return value is the exceeded limit:

static long clamp(long z, long lowLimit, long highLimit) {   if (z < lowLimit)     return lowLimit;   else if (z > highLimit)     return highLimit;   return z; }

If curly bracket-enclosed code blocks are used after if or else, those blocks themselves can contain if statements. The following code fragment uses nested if statements:

if (x > 1000000) {   // x is big.   if (x%2 == 0)     System.out.println("Big and even.");   else     System.out.println("Big and odd."); } else {   // x is little.   if (x%2 == 0)     System.out.println("Small and even.");   else     System.out.println("Small and odd."); }
Note

There is no limit to how deeply you can nest if statements. Of course, if you nest too deeply, your code becomes difficult to read and understand. See the "Nesting" section later in this chapter for an explanation of this technique.

else if

In the previous section, you learned how to follow an if statement with an else statement. You can also follow an if statement with an arbitrary number of else if statements. An else if statement is like an else statement, but it is followed by a parenthetical boolean expression and then by a single statement or curly bracket-enclosed block. As you might expect, the single statement or curly bracket-enclosed block is executed only if the boolean expression evaluates to true. There is no limit to the number of else if statements that may follow an if statement, and the last else if statement may be followed by an else statement.

The following example is a method that prints out one of a number of possible messages, based on the size of the z argument:

static void howBig(double z) {   if (z < 0.001)     System.out.println("Very tiny");   else if (z < 1)     System.out.println("Tiny");   else if (z < 100)     System.out.println("Medium");   else if (z < 100000)     System.out.println("Large");   else     System.out.println("Very large"); }

Note that the series of tests on the value of z begins with a straightforward if statement, followed by three else if statements. The else statement comes at the end, which is the only place where it may appear.

Before we continue, let's take a moment to appreciate the power of the various versions of the if statement. The Java functionality presented in the previous chapters of this book, while impressive, amounts to using your computer as a very fast calculator. For instance, a method would always process its arguments in exactly the same way. With the introduction of if statements, we have programs that can react flexibly. The howBig method, for example, can react flexibly to the value of its z argument.

Later in this chapter we will examine loops, which introduce an additional level of flexibility. But first, let's look at two more kinds of conditional execution: the ternary operator and the switch statement.

The Ternary Operator

In Chapter 3, "Operations," we looked at Java's unary and binary operators. Now let's look at the ternary operator. The name ternary just means that there are three operands. Since there are three, we will need two symbols to separate them: the question mark (?) and the colon (:). The operator is used like this:

 boolean_expression ? value_1 : value_2 

The value of the ternary operation depends on the value of the boolean expression. If the boolean expression evaluates to true, the value of the overall operation is value_1. If the boolean expression evaluates to false, the value of the overall operation is value_2.

Typically, a ternary operation appears on the right-hand side of an assignment. For example, suppose you want radius to be 10 if mass is less than or equal to 50,000; otherwise, you want radius to be 99. Without the ternary operator, you could do it this way:

if (mass <= 50000)   radius = 10; else   radius = 99;

You can rewrite this in a single line with the ternary operator:

radius = mass <= 50000 ? 10 : 99;

The boolean expression does not need to appear in parentheses, but the line is more readable like this:

radius = (mass <= 50000) ? 10 : 99;

The ternary operator is a convenient replacement for an if...else expression.

Now let's look at the switch statement, which is a convenient replacement for a sequence of if...else expressions.

switch

In the previous section, you saw how the ternary operator can replace certain if...else structures. We will now look at the switch statement, which can replace entire chains of if...else if...else if structures.

Suppose you wanted to write some code that takes special actions if the value of a char called theChar is a vowel (a, e, i, o, or u). The special actions consist of printing a message and setting the value of an int called vowelNum. Using if and else, you could write the code as follows:

if (theChar == 'a') {   System.out.println("a is a vowel.");   vowelNum = 0; } else if (theChar == 'e') {   System.out.println("e is a vowel.");   vowelNum = 1; } else if (theChar == 'i') {   System.out.println("i is a vowel.");   vowelNum = 2; } else if (theChar == 'o') {   System.out.println("o is a vowel.");   vowelNum = 3; } else if (theChar == 'u') {   System.out.println("u is a vowel.");   vowelNum = 4; }

This can be rewritten as follows, using a switch statement:

switch (theChar) {   case 'a':     System.out.println("a is a vowel.");     vowelNum = 0;     break;   case 'e':     System.out.println("e is a vowel.");     vowelNum = 1;     break;   case 'i':     System.out.println("i is a vowel.");     vowelNum = 2;     break;   case 'o':     System.out.println("o is a vowel.");     vowelNum = 3;     break;   case 'u':     System.out.println("u is a vowel.");     vowelNum = 4;     break; } 

The value in parentheses just after the switch keyword is called the expression of the switch statement, and it must be of type byte, short, char, or int. (This example assumes that theChar has been declared to be a char.) When the switch code is executed, Java searches through the case statements, looking for one that matches the expression's value. If no match is found, nothing happens; execution continues after the closing curly bracket. If a match is found, control jumps to the first executable line following the case statement. Then execution proceeds line by line until a break statement is reached. At this point, execution of the switch code is terminated, and control continues after the closing curly bracket.

switch and default

The keyword default, followed by a colon, can appear in place of a case statement. The code following the default statement is executed if none of the case statements match the expression. For example, suppose you want to modify your code so that it prints out "Not a vowel" if theChar is not a vowel. If you couldn't use a switch statement, you would do the following:

if (theChar == 'a') {   System.out.println("a is a vowel.");   vowelNum = 0; } else if (theChar == 'e') {   System.out.println("e is a vowel.");   vowelNum = 1; } else if (theChar == 'i') {   System.out.println("i is a vowel.");   vowelNum = 2; } else if (theChar == 'o') {   System.out.println("o is a vowel.");   vowelNum = 3; } else if (theChar == 'u') {   System.out.println("u is a vowel.");   vowelNum = 4; } else   System.out.println("Not a vowel.");

This code is the same as the original solution, but with a final else at the end. The following code uses a switch statement with a default block to achieve the same result:

switch (theChar) {   case 'a':     System.out.println("a is a vowel.");     vowelNum = 0;     break;   case 'e':     System.out.println("e is a vowel.");     vowelNum = 1;     break;   case 'i':     System.out.println("i is a vowel.");     vowelNum = 2;     break;   case 'o':     System.out.println("o is a vowel.");     vowelNum = 3;     break;   case 'u':     System.out.println("u is a vowel.");     vowelNum = 4;     break;   default:     System.out.println("Not a vowel.");     break; }

When you look at all four versions of this example, you can see that using a switch statement does not significantly reduce the number of lines of code (although there is a reduction). The main benefit is readability. The switch versions more clearly tell readers what is happening.

Omitting the break

Once a case block is found that matches the switch statement's expression, execution continues until a break is reached or the switch statement's closing curly bracket is reached, whichever comes first. If a case block does not end with a break, execution continues past the next case statement and into the code for that case block.

In the previous example, suppose the case block for 'e' did not end with a break statement. (Perhaps due to an innocent oversight. It's only human to forget to type break from time to time.) The code would then look like this:

      . . .    7. case 'e':    8.   System.out.println("e is a vowel.");    9.   vowelNum = 1;   10. case 'i':   11.   System.out.println("i is a vowel.");   12.   vowelNum = 2;   13.   break;       . . .

We've added line numbers for easy reference. The switch statement detects that the expression value ('e') matches the case on line 7. The message on line 8 is printed out, and then at line 9 vowelNum is set to 1. Since there is no break at line 10, execution just keeps on going. The case statement at line 10 is ignored, and control flow continues at line 11. The message on line 11 is printed out, and at line 12 vowelNum is set to 2. At last we have a break, so execution of the switch is finished.

This behavior of continuing from one case to the next in the absence of a break statement is called falling through. Falling through is a mixed blessing. When it happens because you forgot to type break for a particular case, it's just a bug that might be hard to find (but easy to fix once it's found).

On the other hand, falling through might be just the behavior that you want. The feature is especially useful when you want to use the same code to process more than one case. The letters y and w are sometimes considered to be vowels. (Y occasionally, as in occasionally; w very rarely, as in crwth, a medieval musical instrument, pronounced "crooth.") You might want to print out a special message if theChar has either of these values. If you were using if...else code, you would insert the following lines:

. . . else if (theChar == 'y'  ||  theChar == 'w')   System.out.println("y and w are sometimes vowels."); . . .

You can incorporate this test into your switch code by inserting the following lines:

. . . case 'y': case 'w':   System.out.println("y and w are sometimes vowels.");   break; . . .

Where should these lines be inserted? Strictly speaking, the cases in a switch statement, including the default code, can appear in any order. However, for readability, it makes the most sense to have the cases appear in their natural order (numerical or alphabetical), with the default code appearing last.

Now that we have looked at Java's conditional code, we can turn our attention to loops.




Ground-Up Java
Ground-Up Java
ISBN: 0782141900
EAN: 2147483647
Year: 2005
Pages: 157
Authors: Philip Heller

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net