| ## Java 1.1 Unleashed # - 4 - Expressions, Operators, and Control Structures by Michael Morrison IN THIS CHAPTER Expressions and Operators Control Structures In Chapter 3, "Java Language Fundamentals," you learned about some of the basic components of a Java program. This chapter focuses on how to use these components to do more useful things. Data types are interesting, but without expressions and operators, you can't do much with them. Even expressions and operators alone are somewhat limited in what they can do. Throw in control structures and you have the ability to do some interesting things. This chapter covers all these issues and pulls together many of the missing pieces of the Java programming puzzle you've begun to assemble. You'll not only expand your knowledge of the Java language a great deal, you'll also learn what it takes to write some more interesting programs. ## Expressions and Operators Once you create variables, you typically want to do something with them. Operators enable you to perform an evaluation or computation on a data object or objects. Operators applied to variables and literals form expressions. An expression can be thought of as a programmatic equation. More formally, an expression is a sequence of one or more data objects (operands) and zero or more operators that produce a result. An example of an expression follows: `x = y / 3;``` In this expression, `x` and `y` are variables, `3` is a literal, and `=` and `/` are operators. This expression states that the `y` variable is divided by `3` using the division operator (`/`), and the result is stored in `x` using the assignment operator (`=`). Notice that the expression was described from right to left. Although this approach of analyzing the expression from right to left is useful in terms of showing the assignment operation, most Java expressions are, in fact, evaluated from left to right. You get a better feel for this in the next section. ### Operator Precedence Even though Java expressions are typically evaluated from left to right, there still are many times when the result of an expression would be indeterminate without other rules. The following expression illustrates the problem: `x = 2 * 6 + 16 / 4``` Strictly using the left-to-right evaluation of the expression, the multiplication operation `2 * 6` is carried out first, which leaves a result of `12`. The addition operation `12 + 16` is then performed, which gives a result of `28`. The division operation `28 / 4` is then performed, which gives a result of `7`. Finally, the assignment operation `x = 7` is handled, in which the number `7` is assigned to the variable `x`. If you have some experience with operator precedence from another language, you might already be questioning the evaluation of this expression, and for good reason--it's wrong! The problem is that using a simple left-to-right evaluation of expressions can yield inconsistent results, depending on the order of the operators. The solution to this problem lies in operator precedence, which determines the order in which operators are evaluated. Every Java operator has an associated precedence. Following is a list of all the Java operators from highest to lowest precedence. In this list of operators, all the operators in a particular row have equal precedence. The precedence level of each row decreases from top to bottom. This means that the `[]` operator has a higher precedence than the `*` operator, but the same precedence as the `()` operator.
`.` | `[]` | `()` |
`++` | `--` | `!` | `~`
`*` | `/` | `%` |
`+` | `-` |  |
`<<` | `>>` | `>>>` |
`<` | `>` | `<=` | `>=`
`==` | `!=` |  |
`&` |  |  |
`^` |  |  |
`&&` |  |  |
`||` |  |  |
`?:` |  |  |
= |  |  |
Evaluation of expressions still moves from left to right, but only when dealing with operators that have the same precedence. Otherwise, operators with a higher precedence are evaluated before operators with a lower precedence. Knowing this, take another look at the sample equation: `x``= 2 * 6 + 16 / 4``` Before using the left-to-right evaluation of the expression, first look to see whether any of the operators have differing precedence. Indeed they do! The multiplication (`*`) and division (`/`) operators both have the highest precedence, followed by the addition operator (`+`), and then the assignment operator (`=`). Because the multiplication and division operators share the same precedence, evaluate them from left to right. Doing this, you first perform the multiplication operation `2 * 6` with the result of `12`. You then perform the division operation `16 / 4`, which results in `4`. After performing these two operations, the expression looks like this: `x = 12 + 4;``` Because the addition operator has a higher precedence than the assignment operator, you perform the addition operation `12 + 4` next, resulting in `16`. Finally, the assignment operation `x = 16` is processed, resulting in the number `16` being assigned to the variable `x`. As you can see, evaluating the expression using operator precedence yields a completely different result. Just to get the point across, take a look at another expression that uses parentheses for grouping purposes: `x = 2 * (11 - 7);``` Without the grouping parentheses, you would perform the multiplication operation first and then the subtraction operation. However, referring back to the precedence list, the `()` operator comes before all other operators. So the subtraction operation `11 - 7` is performed first, yielding `4` and the following expression: `x = 2 * 4;``` The rest of the expression is easily resolved with a multiplication operation and an assignment operation to yield a result of `8` in the variable `x`. ### Integer Operators There are three types of operations that can be performed on integers: unary, binary, and relational. Unary operators act on only single integer numbers, and binary operators act on pairs of integer numbers. Both unary and binary integer operators typically return integer results. Relational operators, on the other hand, act on two integer numbers but return a boolean result rather than an integer. Unary and binary integer operators typically return an `int` type. For all operations involving the types `byte`, `short`, and `int`, the result is always an `int`. The only exception to this rule is when one of the operands is a `long`, in which case the result of the operation is also of type `long`. #### Unary Integer Operators Unary integer operators act on a single integer. Table 4.1 lists the unary integer operators. #### Table 4.1. The unary integer operators.
Description | Operator
Increment | `++`
Decrement | `--`
Negation | `-`
Bitwise complement | `~`
The increment and decrement operators (`++` and `--`) increase and decrease integer variables by 1. Similar to their complements in C and C++, these operators can be used in either prefix or postfix form. A prefix operator takes effect before the evaluation of the expression it is in; a postfix operator takes effect after the expression has been evaluated. Prefix unary operators are placed immediately before the variable; postfix unary operators are placed immediately following the variable. Following are examples of each type of operator: `y = ++x;` z = x--; In the first example, `x` is prefix incremented, which means that it is incremented before being assigned to `y`. In the second example, `x` is postfix decremented, which means that it is decremented after being assigned to `z`. In the latter case, `z` is assigned the value of `x` before `x` is decremented. Listing 4.1 contains the `IncDec` program, which uses both types of operators. Please note that the `IncDec` program is actually implemented in the Java class `IncDec`. This is a result of the object-oriented structure of Java, which requires programs to be implemented as classes. When you see a reference to a Java program, keep in mind that it is really referring to a Java class. #### Listing 4.1. The IncDec class.
    class IncDec {
      public static void main (String args[]) {
        int x = 8, y = 13;
        System.out.println("x = " + x);
        System.out.println("y = " + y);
        System.out.println("++x = " + ++x);
        System.out.println("y++ = " + y++);
        System.out.println("x = " + x);
        System.out.println("y = " + y);
      }

    }
The `IncDec` program produces the following results:
    x = 8
    y = 13
    ++x = 9
    y++ = 13
    x = 9
    y = 14
The negation unary integer operator (`-`) is used to change the sign of an integer value. This operator is as simple as it sounds, as indicated by the following example: `x = 8;` y = -x; In this example, `x` is assigned the literal value `8` and then is negated and assigned to `y`. The resulting value of `y` is `-8`. To see this code in a real Java program, check out the `Negation` program in Listing 4.2. #### Listing 4.2. The Negation class.
    class Negation {
      public static void main (String args[]) {
        int x = 8;
        System.out.println("x = " + x);
        int y = -x;
        System.out.println("y = " + y);
      }

    }
The last Java unary integer operator is the bitwise complement operator (`~`), which performs a bitwise negation of an integer value. Bitwise negation means that each bit in the number is toggled. In other words, all the binary `0`s become `1`s and all the binary `1`s become `0`s. Take a look at an example very similar to the one for the negation operator: `x = 8;` y = ~x; In this example, `x` is assigned the literal value `8` again, but it is bitwise complemented before being assigned to `y`. What does this mean? Well, without getting into the details of how integers are stored in memory, it means that all the bits of the variable `x` are flipped, yielding a decimal result of `-9`. This result has to do with the fact that negative numbers are stored in memory using a method known as two's complement (see the following note). If you're having trouble believing any of this, try it yourself with the `BitwiseComplement` program shown in Listing 4.3. NOTE: Integer numbers are stored in memory as a series of binary bits that can each have a value of `0` or `1`. A number is considered negative if the highest-order bit in the number is set to `1`. Because a bitwise complement flips all the bits in a number--including the high-order bit--the sign of a number is reversed. #### Listing 4.3. The BitwiseComplement class.
    class BitwiseComplement {
      public static void main (String args[]) {
        int x = 8;
        System.out.println("x = " + x);
        int y = ~x;
        System.out.println("y = " + y);
      }

    }
#### Binary Integer Operators Binary integer operators act on pairs of integers. Table 4.2 lists the binary integer operators. #### Table 4.2. The binary integer operators.
Description | Operator
Addition | `+`
Subtraction | `-`
Multiplication | `*`
Division | `/`
Modulus | `%`
Bitwise `AND` | `&`
Bitwise `OR` | `|`
Bitwise `XOR` | `^`
Left-shift | `<<`
Right-shift | `>>`
Zero-fill-right-shift | `>>>`
The addition, subtraction, multiplication, and division operators (`+`, `-`, `*`, and `/`) all do what you expect them to. An important thing to note is how the division operator works; because you are dealing with integer operands, the division operator returns an integer divisor. In cases where the division results in a remainder, the modulus operator (`%`) can be used to get the remainder value. Listing 4.4 contains the `Arithmetic` program, which shows how the basic binary integer arithmetic operators work. #### Listing 4.4. The Arithmetic class.
    class Arithmetic {
      public static void main (String args[]) {
        int x = 17, y = 5;
        System.out.println("x = " + x);
        System.out.println("y = " + y);
        System.out.println("x + y = " + (x + y));
        System.out.println("x - y = " + (x - y));
        System.out.println("x * y = " + (x * y));
        System.out.println("x / y = " + (x / y));
        System.out.println("x % y = " + (x % y));
      }

    }
The results of running the `Arithmetic` program follow:
    x = 17
    y = 5
    x + y = 22
    x - y = 12
    x * y = 85
    x / y = 3
    x % y = 2
These results shouldn't surprise you too much. Just notice that the division operation `x / y`, which boils down to `17 / 5`, yields the result `3`. Also notice that the modulus operation `x % y`, which is resolved down to `17 % 5`, ends with a result of `2` (the remainder of the integer division). Mathematically, a division by zero results in an infinite result. Because representing infinite numbers is a big problem for computers, division or modulus operations by zero result operations in an error. To be more specific, a runtime exception is thrown. You learn a lot more about exceptions in Chapter 7, "Exception Handling." The bitwise `AND`, `OR`, and `XOR` operators (`&`, `|`, and `^`) all act on the individual bits of an integer. These operators are sometimes useful when an integer is being used as a bit field. An example of this is when an integer is used to represent a group of binary flags. An `int` is capable of representing up to 32 different flags, because it is stored in 32 bits. Listing 4.5 contains the program `Bitwise`, which shows how to use the binary bitwise integer operators. NOTE: Java actually includes a class that provides specific support for storing binary flags. The class is called `BitSet`, and you learn about it in Chapter 11, "The Utilities Package." #### Listing 4.5. The Bitwise class.
    class Bitwise {
      public static void main (String args[]) {
        int x = 5, y = 6;
        System.out.println("x = " + x);
        System.out.println("y = " + y);
        System.out.println("x & y = " + (x & y));
        System.out.println("x | y = " + (x | y));
        System.out.println("x ^ y = " + (x ^ y));
      }

    }
The output of running `Bitwise` follows:
    x = 5
    y = 6
    x & y = 4
    x | y = 7
    x ^ y = 3
To understand this output, you must first understand the binary equivalents of each decimal number. In `Bitwise`, the variables `x` and `y` are set to `5` and `6`, which correspond to the binary numbers `0101` and `0110`. The bitwise `AND` operation compares each bit of each number to see whether they are the same. It then sets the resulting bit to `1` if both bits being compared are `1`; it sets the resulting bit to `0` otherwise. The result of the bitwise `AND` operation on these two numbers is `0100` in binary, or decimal `4`. The same logic is used for both of the other operators, except that the rules for comparing the bits are different. The bitwise `OR` operator sets the resulting bit to `1` if either of the bits being compared is `1`. For these numbers, the result is `0111` binary, or `7` decimal. Finally, the bitwise `XOR` operator sets resulting bits to `1` if exactly one of the bits being compared is `1`, and `0` otherwise. For these numbers, the result is `0011` binary, or `3` decimal. The left-shift, right-shift, and zero-fill-right-shift operators (`<<`, `>>`, and `>>>`) shift the individual bits of an integer by a specified integer amount. Following are some examples of how these operators are used: `x << 3;` y >> 7; z >>> 2; In the first example, the individual bits of the integer variable `x` are shifted to the left three places. In the second example, the bits of `y` are shifted to the right seven places. Finally, the third example shows `z` being shifted to the right two places, with zeros shifted into the two leftmost places. To see the shift operators in a real program, check out `Shift` in Listing 4.6. #### Listing 4.6. The Shift class.
    class Shift {
      public static void main (String args[]) {
        int x = 7;
        System.out.println("x = " + x);
        System.out.println("x >> 2 = " + (x >> 2));
        System.out.println("x << 1 = " + (x << 1));
        System.out.println("x >>> 1 = " + (x >>> 1));
      }
    }
The output of `Shift` follows:
    x = 7
    x >> 2 = 1
    x << 1 = 14
    x >>> 1 = 3
The number being shifted in this case is the decimal `7`, which is represented in binary as `0111`. The first right-shift operation shifts the bits two places to the right, resulting in the binary number `0001`, or decimal `1`. The next operation, a left-shift, shifts the bits one place to the left, resulting in the binary number `1110`, or decimal `14`. The last operation is a zero-fill-right-shift, which shifts the bits one place to the right, resulting in the binary number `0011`, or decimal `3`. Pretty simple, eh? And you probably thought it was difficult working with integers at the bit level! Based on these examples, you may be wondering what the difference is between the right-shift (`>>`) and zero-fill-right-shift (`>>>`) operators. The right-shift operator appears to shift zeros into the leftmost bits, just like the zero-fill-right-shift operator, right? Well, when dealing with positive numbers, there is no difference between the two operators; they both shift zeros into the upper bits of a number. The difference arises when you start shifting negative numbers. Remember that negative numbers have the high-order bit set to `1`. The right-shift operator preserves the high-order bit and effectively shifts the lower 31 bits to the right. This behavior yields results for negative numbers similar to those for positive numbers. That is, `-8` shifted right by one results in `-4`. The zero-fill-right-shift operator, on the other hand, shifts zeros into all the upper bits, including the high-order bit. When this shifting is applied to negative numbers, the high-order bit becomes `0` and the number becomes positive. #### Relational Integer Operators The last group of integer operators is the relational operators, which all operate on integers but return a type `boolean`. Table 4.3 lists the relational integer operators. #### Table 4.3. The relational integer operators.
Description | Operator
Less-than | `<`
Greater-than | `>`
Less-than-or-equal-to | `<=`
Greater-than-or-equal-to | `>=`
Equal-to | `==`
Not-equal-to | `!=`
These operators all perform comparisons between integers. Listing 4.7 contains the `Relational` program, which demonstrates the use of the relational operators with integers. #### Listing 4.7. The Relational class.
    class Relational {
      public static void main (String args[]) {
        int x = 7, y = 11, z = 11;
        System.out.println("x = " + x);
        System.out.println("y = " + y);
        System.out.println("z = " + z);
        System.out.println("x < y = " + (x < y));
        System.out.println("x > z = " + (x > z));
        System.out.println("y <= z = " + (y <= z));
        System.out.println("x >= y = " + (x >= y));
        System.out.println("y == z = " + (y == z));
        System.out.println("x != y = " + (x != z));
      }
    }
The output of running `Relational` follows:
    x = 7
    y = 11
    z = 11
    x < y = true
    x > z = false
    y <= z = true
    x >= y = false
    y == z = true
    x != y = true
As you can see, the `println()` method is smart enough to print boolean results correctly as `true` and `false`. ### Floating-Point Operators Similar to integer operators, there are three types of operations that can be performed on floating-point numbers: unary, binary, and relational. Unary operators act only on single floating-point numbers, and binary operators act on pairs of floating-point numbers. Both unary and binary floating-point operators return floating-point results. Relational operators, however, act on two floating-point numbers but return a boolean result. Unary and binary floating-point operators return a `float` type if both operands are of type `float`. If one or both of the operands are of type `double`, however, the result of the operation is of type `double`. #### Unary Floating-Point Operators The unary floating point operators act on a single floating-point number. Table 4.4 lists the unary floating-point operators. #### Table 4.4. The unary floating-point operators.
Description | Operator
Increment | `++`
Decrement | `--`
As you can see, the only two unary floating-point operators are the increment and decrement operators. These two operators respectively add and subtract `1.0` from their floating-point operand. #### Binary Floating-Point Operators The binary floating-point operators act on a pair of floating-point numbers. Table 4.5 lists the binary floating-point operators. #### Table 4.5. The binary floating-point operators.
Description | Operator
Addition | `+`
Subtraction | `-`
Multiplication | `*`
Division | `/`
Modulus | `%`
The binary floating-point operators consist of the four traditional binary operations (`+`, `-`, `*`, `/`), along with the modulus operator (`%`). You might be wondering how the modulus operator fits in here, considering that its use as an integer operator relied on an integer division. If you recall, the integer modulus operator returned the remainder of an integer division of the two operands. But a floating-point division never results in a remainder, so what does a floating-point modulus do? The floating-point modulus operator returns the floating-point equivalent of an integer division. What this means is that the division is carried out with both floating-point operands, but the resulting divisor is treated as an integer, resulting in a floating-point remainder. Listing 4.8 contains the `FloatMath` program, which shows how the floating-point modulus operator works along with the other binary floating-point operators. #### Listing 4.8. The FloatMath class.
    class FloatMath {
      public static void main (String args[]) {
        float x = 23.5F, y = 7.3F;
        System.out.println("x = " + x);
        System.out.println("y = " + y);
        System.out.println("x + y = " + (x + y));
        System.out.println("x - y = " + (x - y));
        System.out.println("x * y = " + (x * y));
        System.out.println("x / y = " + (x / y));
        System.out.println("x % y = " + (x % y));
      }
    }
The output of `FloatMath` follows:
    x = 23.5
    y = 7.3
    x + y = 30.8
    x - y = 16.2
    x * y = 171.55
    x / y = 3.21918
    x % y = 1.6
The first four operations no doubt performed as you expected, taking the two floating-point operands and yielding a floating-point result. The final modulus operation determined that `7.3` divides into `23.5` an integral amount of `3` times, leaving a remaining result of `1.6`. #### Relational Floating-Point Operators The relational floating-point operators compare two floating-point operands, leaving a boolean result. The floating-point relational operators are the same as the integer relational operators listed in Table 4.3, earlier in this chapter, except that they work on floating-point numbers. ### Boolean Operators Boolean operators act on boolean types and return a boolean result. The boolean operators are listed in Table 4.6. #### Table 4.6. The boolean operators.
Description | Operator
Evaluation `AND` | `&`
Evaluation `OR` | `|`
Evaluation `XOR` | `^`
Logical `AND` | `&&`
Logical `OR` | `||`
Negation | `!`
Equal-to | `==`
Not-equal-to | `!=`
Conditional | `?:`
The evaluation operators (`&`, `|`, and `^`) evaluate both sides of an expression before determining the result. The logical operators (`&&` and `||`) avoid the right-side evaluation of the expression if it is not needed. To better understand the difference between these operators, take a look at the following two expressions:
    boolean result = isValid & (Count > 10);
    boolean result = isValid && (Count > 10);
The first expression uses the evaluation `AND` operator (`&`) to make an assignment. In this case, both sides of the expression are always evaluated, regardless of the values of the variables involved. In the second example, the logical `AND` operator (`&&`) is used. This time, the `isValid` boolean value is first checked. If it is `false`, the right side of the expression is ignored and the assignment is made. This operator is more efficient because a `false` value on the left side of the expression provides enough information to determine the `false` outcome. Although the logical operators are more efficient than the evaluation operators, there still may be times when you want to use the evaluation operators to ensure that the entire expression is evaluated. The following code shows how the evaluation `AND` operator is necessary for the complete evaluation of an expression:
    while ((++x < 10) && (++y < 15)) {
      System.out.println(x);
      System.out.println(y);

    }
In this example, the second expression (`++y < 15`) is evaluated after the last pass through the loop because of the evaluation `AND` operator. If the logical `AND` operator had been used, the second expression would not have been evaluated and `y` would not have been incremented after the last time around. The three boolean operators--negation, equal-to, and not-equal-to (`!`, `==`, and `!=`)--perform exactly as you might expect. The negation operator toggles the value of a boolean from `false` to `true` or from `true` to `false`, depending on the original value. The equal-to operator simply determines whether two boolean values are equal (both `true` or both `false`). Similarly, the not-equal-to operator determines whether two boolean operands are unequal. The conditional boolean operator (`?:`) is the most unique of the boolean operators and is worth a closer look. This operator also is known as the ternary operator because it takes three items: a condition and two expressions. The syntax for the conditional operator follows:
    Condition ? Expression1 : Expression2
The Condition, which itself is a boolean, is first evaluated to determine whether it is `true` or `false`. If Condition evaluates to a `true` result, Expression1 is evaluated. If Condition ends up being `false`, Expression2 is evaluated. To get a better feel for the conditional operator, check out the `Conditional` program in Listing 4.9. #### Listing 4.9. The Conditional class.
    class Conditional {
      public static void main (String args[]) {
        int x = 0;
        boolean isEven = false;
        System.out.println("x = " + x);
        x = isEven ? 4 : 7;
        System.out.println("x = " + x);
      }

    }
The results of the `Conditional` program follow:
    x = 0
    x = 7
The integer variable `x` is first assigned a value of `0`. The boolean variable `isEven` is assigned a value of `false`. Using the conditional operator, the value of `isEven` is checked. Because it is `false`, the second expression of the conditional is used, which results in the value `7` being assigned to `x`. ### String Operator Just as integers, floating-point numbers, and booleans can be, strings can be manipulated with operators. Actually, there is only one string operator: the concatenation operator (`+`). The concatenation operator for strings works very similarly to the addition operator for numbers--it adds strings together. The concatenation operator is demonstrated in the `Concatenation` program shown in Listing 4.10. #### Listing 4.10. The Concatenation class.
    class Concatenation {
      public static void main (String args[]) {
        String firstHalf = "What " + "did ";
        String secondHalf = "you " + "say?";
        System.out.println(firstHalf + secondHalf);
      }

    }
The output of `Concatenation` follows:
    What did you say?
In the `Concatenation` program, literal strings are concatenated to make assignments to the two string variables, `firstHalf` and `secondHalf`, at time of creation. The two string variables are then concatenated within the call to the `println()` method. ### Assignment Operators One final group of operators you haven't seen yet is the assignment operators. Assignment operators actually work with all the fundamental data types. Table 4.7 lists the assignment operators. #### Table 4.7. The assignment operators.
Description | Operator
Simple | `=`
Addition | `+=`
Subtraction | `-=`
Multiplication | `*=`
Division | `/=`
Modulus | `%=`
`AND` | `&=`
`OR` | `|=`
`XOR` | `^=`
With the exception of the simple assignment operator (`=`), the assignment operators function exactly like their nonassignment counterparts, except that the resulting value is stored in the operand on the left side of the expression. Take a look at the following examples: `x += 6;` x *= (y - 3); In the first example, `x` and `6` are added and the result stored in `x`. In the second example, `3` is subtracted from `y` and the result is multiplied by `x`. The final result is then stored in `x`. ## Control Structures Although performing operations on data is very useful, it's time to move on to the issue of program flow control. The flow of your programs is dictated by two different types of constructs: branches and loops. Branches enable you to selectively execute one part of a program instead of another. Loops, on the other hand, provide a means to repeat certain parts of a program. Together, branches and loops provide you with a powerful means to control the logic and execution of your code. ### Branches Without branches or loops, Java code executes in a sequential fashion, as shown in Figure 4.1. Figure 4.1. A program executing sequentially. In Figure 4.1, each statement is executed sequentially. But what if you don't always want every single statement executed? Then you use a branch. Figure 4.2 shows how a conditional branch gives the flow of your code more options. By adding a branch, you give the code two optional routes to take, based on the result of the conditional expression. The concept of branches might seem trivial, but it would be difficult if not impossible to write useful programs without them. Java supports two types of branches: `if-else` branches and `switch` branches. Figure 4.2. A program executing with a branch. #### if-else Branches The `if-else` branch is the most commonly used branch in Java programming. It is used to select conditionally one of two possible outcomes. The syntax for the `if-else` statement follows:
    if (Condition)
      Statement1
    else
      Statement2
If the boolean Condition evaluates to `true`, Statement1 is executed. Likewise, if Condition evaluates to `false`, Statement2 is executed. The following example shows how to use an `if-else` statement:
    if (isTired)
      timeToEat = true;
    else

      timeToEat = false;
If the boolean variable `isTired` is `true`, the first statement is executed and `timeToEat` is set to `true`. Otherwise, the second statement is executed and `timeToEat` is set to `false`. You may have noticed that the `if-else` branch works in a manner very similar to the conditional operator (`?:`) described earlier in this chapter. In fact, you can think of the `if-else` branch as an expanded version of the conditional operator. One significant difference between the two is that you can include compound statements in an `if-else` branch, which you cannot do with the conditional operator. NOTE: Compound statements are blocks of code surrounded by curly braces `{}` that appear as a single, or simple, statement to an outer block of code. If you have only a single statement that you want to execute conditionally, you can leave off the `else` part of the branch, as shown in the following example:
    if (isThirsty)
      pourADrink = true;
On the other hand, if you need more than two conditional outcomes, you can string together a series of `if-else` branches to get the desired effect. The following example shows multiple `if-else` branches used to switch between different outcomes:
    if (x == 0)
      y = 5;
    else if (x == 2)
      y = 25;
    else if (x >= 3)
      y = 125;
In this example, three different comparisons are made, each with its own statement executed on a `true` conditional result. Notice, however, that subsequent `if-else` branches are in effect nested within the previous branch. This arrangement ensures that at most one statement is executed. The last important topic to cover in regard to `if-else` branches is compound statements. As mentioned in the preceding note, a compound statement is a block of code surrounded by curly braces that appears to an outer block as a single statement. Following is an example of a compound statement used with an `if` branch:
    if (performCalc) {
      x += y * 5;
      y -= 10;
      z = (x - 3) / y;
    }
Sometimes, when nesting `if-else` branches, it is necessary to use curly braces to distinguish which statements go with which branch. The following example illustrates the problem:
    if (x != 0)
      if (y < 10)
        z = 5;
    else
      z = 7;
In this example, the style of indentation indicates that the `else` branch belongs to the first (outer) `if`. However, because there was no grouping specified, the Java compiler assumes that the `else` goes with the inner `if`. To get the desired results, you must modify the code as follows:
    if (x != 0) {
      if (y < 10)
        z = 5;
    }
    else
      z = 7;
The addition of the curly braces tells the compiler that the inner `if` is part of a compound statement; more importantly, it completely hides the `else` branch from the inner `if`. Based on what you learned from the discussion of blocks and scope in Chapter 3, "Java Language Fundamentals," you can see that code within the inner `if` has no way of accessing code outside its scope, including the `else` branch. Listing 4.11 contains the source code for the `IfElseName` class, which uses a lot of what you've learned so far. #### Listing 4.11. The IfElseName class.
    class IfElseName {
      public static void main (String args[]) {
        char firstInitial = (char)-1;
        System.out.println("Enter your first initial:");
        try {
          firstInitial = (char)System.in.read();
        }
        catch (Exception e) {
          System.out.println("Error: " + e.toString());
        }
        if (firstInitial == -1)
          System.out.println("Now what kind of name is that?");
        else if (firstInitial == 'j')
          System.out.println("Your name must be Jules!");
        else if (firstInitial == 'v')
          System.out.println("Your name must be Vincent!");
        else if (firstInitial == 'z')
          System.out.println("Your name must be Zed!");
        else
          System.out.println("I can't figure out your name!");
      }
    }
When typing the letter v in response to the input message, `IfElseName` yields the following results:
    Your name must be Vincent!
The first thing in `IfElseName` you probably are wondering about is the `read()` method. The `read()` method simply reads a character from the standard input stream (`System.in`), which is typically the keyboard. Notice that a cast is used because `read()` returns an `int` type. Once the input character has been successfully retrieved, a succession of `if-else` branches is used to determine the proper output. If there are no matches, the final `else` branch is executed, which notifies users that their names could not be determined. Notice that the value of `read()` is checked to see whether it is equal to `-1`. The `read()` method returns `-1` if it has reached the end of the input stream. NOTE: You may have noticed that the call to the `read()` method in `IfElseName` is enclosed within a `try-catch` clause. The `try-catch` clause is part of Java's support for exception handling and is used in this case to trap errors encountered while reading input from the user. You'll learn more about exceptions and the `try-catch` clause in Chapter 7, "Exception Handling." #### switch Branches Similar to the `if-else` branch, the `switch` branch is specifically designed to conditionally switch among multiple outcomes. The syntax for the `switch` statement follows:
    switch (Expression) {
      case Constant1:
        StatementList1
      case Constant2:
        StatementList2
      _
      default:
        DefaultStatementList
    }
The `switch` branch evaluates and compares Expression to all the `case` constants and branches the program's execution to the matching `case` statement list. If no `case` constants match Expression, the program branches to the DefaultStatementList, if one has been supplied (the DefaultStatementList is optional). You might be wondering what a statement list is. A statement list is simply a series, or list, of statements. Unlike the `if-else` branch, which directs program flow to a simple or compound statement, the `switch` branch directs the flow to a list of statements. When the program execution moves into a `case` statement list, it continues from there in a sequential manner. To better understand this, take a look at Listing 4.12, which contains a `switch` version of the name program developed earlier with `if-else` branches. #### Listing 4.12. The SwitchName1 class.
    class SwitchName1 {
      public static void main (String args[]) {
        char firstInitial = (char)-1;
        System.out.println("Enter your first initial:");
        try {
          firstInitial = (char)System.in.read();
        }
        catch (Exception e) {
          System.out.println("Error: " + e.toString());
        }
        switch(firstInitial) {
          case (char)-1:
            System.out.println("Now what kind of name is that?");
          case 'j':
            System.out.println("Your name must be Jules!");
          case 'v':
            System.out.println("Your name must be Vincent!");
          case 'z':
            System.out.println("Your name must be Zed!");
          default:
            System.out.println("I can't figure out your name!");
        }
      }

    }
When typing the letter v in response to the input message, `SwitchName1` produces the following results:
    Your name must be Vincent!
    Your name must be Zed!
    I can't figure out your name!
Hey, what's going on here? That output definitely does not look right. The problem lies in the way the `switch` branch controls program flow. The `switch` branch matched the `v` entered with the correct `case` statement, as shown in the first string printed. However, the program continued executing all the `case` statements from that point onward, which is not what you wanted. The solution to the problem lies in the `break` statement. The `break` statement forces a program to break out of the block of code it is currently executing. Check out the new version of the program in Listing 4.13, which has `break` statements added where appropriate. #### Listing 4.13. The SwitchName2 class.
    class SwitchName2 {
      public static void main (String args[]) {
        char firstInitial = (char)-1;
        System.out.println("Enter your first initial:");
        try {
          firstInitial = (char)System.in.read();
        }
        catch (Exception e) {
          System.out.println("Error: " + e.toString());
        }
        switch(firstInitial) {
          case (char)-1:
            System.out.println("Now what kind of name is that?");
            break;
          case 'j':
            System.out.println("Your name must be Jules!");
            break;
          case 'v':
            System.out.println("Your name must be Vincent!");
            break;
          case 'z':
            System.out.println("Your name must be Zed!");
            break;
          default:
            System.out.println("I can't figure out your name!");
        }
      }
    }
When you run `SwitchName2` and enter v, you get the following output:
    Your name must be Vincent!
That's a lot better! You can see that placing `break` statements after each `case` statement kept the program from falling through to the next `case` statements. Although you will use `break` statements in this manner the majority of the time, there may still be some situations where you will want a `case` statement to fall through to the next one. ### Loops When it comes to program flow, branches really tell only half of the story; loops tell the other half. Put simply, loops enable you to execute code repeatedly. There are three types of loops in Java: `for` loops, `while` loops, and `do-while` loops. Just as branches alter the sequential flow of programs, so do loops. Figure 4.3 shows how a loop alters the sequential flow of a Java program. #### for Loops The `for` loop provides a means to repeat a section of code a designated number of times. The `for` loop is structured so that a section of code is repeated until some limit has been reached. The syntax for the `for` statement follows:
    for (InitializationExpression; LoopCondition; StepExpression)
      Statement
The `for` loop repeats the Statement lines the number of times that is determined by the InitializationExpression, the LoopCondition, and the StepExpression. The InitializationExpression is used to initialize a loop control variable. The LoopCondition compares the loop control variable to some limit value. Finally, the StepExpression specifies how the loop control variable should be modified before the next iteration of the loop. The following example shows how a `for` loop can be used to print the numbers from `1` to `10`:
    for (int i = 1; i < 11; i++)
      System.out.println(i);
Figure 4.3. A program executing with a loop. First, `i` is declared as an integer. The fact that `i` is declared within the body of the `for` loop might look strange to you at this point. Don't despair--this is completely legal. `i` is initialized to `1` in the InitializationExpression part of the `for` loop. Next, the conditional expression `i < 11` is evaluated to see whether the loop should continue. At this point, `i` is still equal to `1`, so LoopCondition evaluates to `true` and the Statement is executed (the value of `i` is printed to standard output). `i` is then incremented in the StepExpression part of the `for` loop, and the process repeats with the evaluation of LoopCondition again. This continues until LoopCondition evaluates to `false`, which is when `x` equals `11` (ten iterations later). Listing 4.14 shows the `ForCount` program, which shows how to use a `for` loop to count a user-entered amount of numbers. #### Listing 4.14. The ForCount class.
    class ForCount {
      public static void main (String args[]) {
        char input = (char)-1;
        int  numToCount;
        System.out.println("Enter a number to count to between 0 and 10:");
        try {
          input = (char)System.in.read();
        }
        catch (Exception e) {
          System.out.println("Error: " + e.toString());
        }
        numToCount = Character.digit(input, 10);
        if ((numToCount > 0) && (numToCount < 10)) {
          for (int i = 1; i <= numToCount; i++)
            System.out.println(i);
        }
        else
          System.out.println("That number was not between 0 and 10!");
      }
    }
When the `ForCount` program is run and the number `4` is entered, the following output results:
    1
    2
    3
    4
ForCount first prompts the user to enter a number between `0` and `10`. A character is read from the keyboard using the `read()` method and the result is stored in the `input` character variable. The static `digit` method of the `Character` class then is used to convert the character to its base 10 integer representation. This value is stored in the `numToCount` integer variable. `numToCount` is then checked to make sure that it is in the range `0` to `10`. If so, a `for` loop is executed that counts from `1` to `numToCount`, printing each number along the way. If `numToCount` is outside the valid range, an error message is printed. Before you move on, there is one small problem with `ForCount` that you may not have noticed. Run it and try typing in a number greater than `9`. What happened to the error message? The problem is that `ForCount` grabs only the first character it sees from the input. So if you type 10, `ForCount` just gets the `1` and thinks everything is fine. You don't have to worry about fixing this problem right now because it will be resolved when you learn more about input and output in Chapter 12, "The I/O Package." #### while Loops Like the `for` loop, the `while` loop has a loop condition that controls the execution of the loop statement. Unlike the `for` loop, however, the `while` loop has no initialization or step expressions. The syntax for the `while` statement follows:
    while (LoopCondition)
      Statement
If the boolean LoopCondition evaluates to `true`, the Statement is executed and the process starts over. It is important to understand that the `while` loop has no step expression as the `for` loop does. This means that the LoopCondition must somehow be affected by code in the Statement or the loop will infinitely repeat, which is a bad thing. This is bad because an infinite loop causes a program to never exit, which hogs processor time and can ultimately hang the system. Another important thing to notice about the `while` loop is that its LoopCondition occurs before the body of the loop Statement. This means that if the LoopCondition initially evaluates to `false`, the Statement is never executed. Although this may seem trivial, it is in fact the only thing that differentiates the `while` loop from the `do-while` loop, which is discussed in the next section. To better understand how the `while` loop works, take a look at Listing 4.15, which shows how a counting program works using a `while` loop. #### Listing 4.15. The WhileCount class.
    class WhileCount {
      public static void main (String args[]) {
        char input = (char)-1;
        int  numToCount;
        System.out.println("Enter a number to count to between 0 and 10:");
        try {
          input = (char)System.in.read();
        }
        catch (Exception e) {
          System.out.println("Error: " + e.toString());
        }
        numToCount = Character.digit(input, 10);
        if ((numToCount > 0) && (numToCount < 10)) {
          int i = 1;
          while (i <= numToCount) {
            System.out.println(i);
            i++;
          }
        }
        else
          System.out.println("That number was not between 0 and 10!");
      }

    }
Arguably, `WhileCount` doesn't demonstrate the best usage of a `while` loop. Loops that involve counting should almost always be implemented with `for` loops. However, seeing how a `while` loop can be made to imitate a `for` loop can give you insight into the structural differences between the two types of loops. Because `while` loops don't have any type of initialization expression, you first have to declare and initialize the variable `i` to `1`. Next, the loop condition for the `while` loop is established as `i <= numToCount`. Inside the compound `while` statement, you can see a call to the `println()` method, which outputs the value of `i`. Finally, `i` is incremented and program execution resumes back at the `while` loop condition. #### do-while Loops The `do-while` loop is very similar to the `while` loop, as you can see in the following syntax:
    do
      Statement
    while (LoopCondition);
The major difference between the `do-while` loop and the `while` loop is that, in a `do-while` loop, the LoopCondition is evaluated after the Statement is executed. This difference is important because there may be times when you want the Statement code to be executed at least once, regardless of the LoopCondition. The Statement is executed initially, and from then on it is executed as long as the LoopCondition evaluates to `true`. As with the `while` loop, you must be careful with the `do-while` loop to avoid creating an infinite loop. An infinite loop occurs when the LoopCondition remains `true` indefinitely. The following example shows a very obvious infinite `do-while` loop:
    do
      System.out.println("I'm stuck!");

    while (true);
Because the LoopCondition is always `true`, the message `I'm Stuck!` is printed forever, or at least until you press Ctrl+C and break out of the program. ### break and continue Statements You've already seen how the `break` statement works with the `switch` branch. The `break` statement is also useful when dealing with loops. You can use the `break` statement to jump out of a loop and effectively bypass the loop condition. Listing 4.16 shows how the `break` statement can help you out of the infinite loop problem shown earlier. #### Listing 4.16. The BreakLoop class.
    class BreakLoop {
      public static void main (String args[]) {
        int i = 0;
        do {
          System.out.println("I'm stuck!");
          i++;
          if (i > 100)
            break;
        }
        while (true);
      }

    }
In `BreakLoop`, a seemingly infinite `do-while` loop is created by setting the loop condition to `true`. However, the `break` statement is used to exit the loop when `i` is incremented past `100`. Another useful statement that works similarly to the `break` statement is the `continue` statement. Unlike `break`, the `continue` statement is useful only when working with loops; it has no real application to the `switch` branch. The `continue` statement works like the `break` statement in that it jumps out of the current iteration of a loop. The difference with `continue` is that program execution is restored to the test condition of the loop. Remember that `break` jumps completely out of a loop. Use `break` when you want to jump out and terminate a loop; use `continue` when you want to jump immediately to the next iteration of the loop. The following example shows the difference between the `break` and `continue` statements:
    int i = 0;
    while (i++ < 100) {
      System.out.println("Looping with i.");
      break;
      System.out.println("Please don't print me!");
    }
    int j = 0;
    while (j++ < 100) {
      System.out.println("Looping with j!");
      continue;
      System.out.println("Please don't print me!");
    }
In this example, the first loop breaks out because of the `break` statement after printing the looping message once. Note that the second message is never printed because the break statement occurs before we get to it. Contrast this with the second loop, which prints the looping message 100 times. The reason for this is that the `continue` statement allows the loop to continue its iterations. In this case, the `continue` statement serves only to skip over the second message, which still isn't printed. ## Summary This chapter covered a lot of territory. You started off by learning about expressions and then moved right into operators, learning how they work and how they affect each data type. You won't regret the time spent working with operators in this chapter--they are at the core of almost every mathematical or logical Java expression. From operators, you moved on to control structures, learning about the various types of branches and loops. Branches and loops provide the means to alter the flow of Java programs and are just as important as operators in Java programming. With the concepts presented in this chapter firmly set in your mind, you are ready to dig a little deeper into Java. Next stop: object-oriented programming with classes, packages, and interfaces!
| ©Copyright, Macmillan Computer Publishing. All rights reserved.