> ### Section 3.5
> The `if` Statement

> THE FIRST OF THE TWO BRANCHING STATEMENTS in Java is the `if` statement, which you have already seen in Section 1. It takes the form

>                  if (boolean-expression)
>                       statement-1
>                  else
>                       statement-2

> As usual, the statements inside an `if` statements can be blocks. The `if` statement represents a two-way branch. The `else` part of an `if` statement -- consisting of the word "else" and the statement that follows it -- can be omitted.

> Now, an `if` statement is, in particular, a statement. This means that either statement-1 or statement-2 in the above `if` statement can itself be an `if` statement. A problem arises, however, if statement-1 is an `if` statement that has no `else` part. This special case is effectively forbidden by the syntax of Java. Suppose, for example, that you type

>                  if ( x > 0 )
>                      if (y > 0)
>                         System.out.println("First case");
>                  else
>                      System.out.println("Second case");

> Now, remember that the way you've indented this doesn't mean anything at all to the computer. You might think that the `else` part is the second half of your "`if (x > 0)`" statement, but the rule that the computer follows attaches the `else` to "`if (y > 0)`", which is closer. That is, the computer reads your statement as if it were formatted:

>                  if ( x > 0 )
>                      if (y > 0)
>                         System.out.println("First case");
>                      else
>                          System.out.println("Second case");

> You can force the computer to use the other interpretation by enclosing the nested `if` in a block:

>                  if ( x > 0 ) {
>                      if (y > 0)
>                         System.out.println("First case");
>                  }
>                  else
>                      System.out.println("Second case");

> These two statements have different meanings: If `x <= 0`, the first statement doesn't print anything, but the second statement prints "Second case.".

> Much more interesting than this technicality is the case where statement-2, the `else` part of the `if` statement, is itself an `if` statement. The statement would look like this (perhaps without the final else part):

>                  if (boolean-expression-1)
>                       statement-1
>                  else
>                       if (boolean-expression-2)
>                           statement-2
>                       else
>                           statement-3

> However, since the computer doesn't care how a program is laid out on the page, this is almost always written in the format:

>                  if (boolean-expression-1)
>                       statement-1
>                  else if (boolean-expression-2)
>                       statement-2
>                  else
>                       statement-3

> You should think of this as a single statement representing a three-way branch. When the computer executes this, one and only one of the three statements -- statement-1, statement-2, or statement-3 -- will be executed. The computer starts by evaluating boolean-expression-1. If it is `true`, the computer executes statement-1 and then jumps all the way to the end of the outer if statement, skipping the other two statements. If boolean-expression-1 is `false`, the computer skips statement-1 and executes the second, nested if statement. To do this, it tests the value of boolean-expression-2 and uses it to decide between statement-2 and statement-3.

> Here is an example that will print out one of three different messages, depending on the value of a variable named `temperature`:

>                 if (temperature < 50)
>                    System.out.println("It's cold.");
>                 else if (temperature < 80)
>                    System.out.println("It's nice.");
>                 else
>                    System.out.println("It's hot.");

> If `temperature` is, say, 42, the first test is `true`. The computer prints out the message "It's cold", and skips the rest -- without even evaluating the second condition. For a temperature of 75, the first test is `false`, so the computer goes on to the second test. This test is `true`, so the computer prints "It's nice" and skips the rest. If the temperature is 173, both of the tests evaluate to `false`, so the computer says "It's hot" (unless its circuits have been fried by the heat, that is).

> You can go on stringing together "else-if's" to make multi-way branches with any number of cases:

>                  if (boolean-expression-1)
>                       statement-1
>                  else if (boolean-expression-2)
>                       statement-2
>                  else if (boolean-expression-3)
>                       statement-3
>                    .
>                    . // (more cases)
>                    .
>                  else if (boolean-expression-N)
>                       statement-N
>                  else
>                       statement-(N+1)

> The computer evaluates boolean expressions one after the other until it comes to one that is `true`. It executes the associated statement and skips the rest. If none of the boolean expressions evaluate to `true`, then the statement in the `else` part is executed. This statement is called a multi-way branch because only one of the statements will be executed. The final `else` part can be omitted. In that case, if all the boolean expressions are false, none of the statements is executed. Of course, each of the statements can be a block, consisting of a number of statements enclosed between { and }. (Admittedly, there is lot of syntax here; as you study and practice, you'll become comfortable with it.)

> As an example of using `if` statements, lets suppose that `x`, `y`, and `z` are variables of type `int`, and that each variable has already been assigned a value. Consider the problem of printing out the values of the three variables in increasing order. For examples, if the values are 42, 17, and 20, then the output should be in the order 17, 20, 42.

> One way to approach this is to ask, where does `x` belong in the list? It comes first if it's less than both `y` and `z`. It comes last if it's greater than both `y` and `z`. Otherwise, it comes in the middle. We can express this with a 3-way `if` statement, but we still have to worry about the order in which `y` and `z` should be printed. In pseudocode,

>                if (x < y && x < z) {
>                    output x, followed by y and z in their correct order
>                }
>                else if (x > y && x > z) {
>                    output y and z in their correct order, followed by x
>                }
>                else {
>                    output x in between y and z in their correct order
>                }

> Determining the relative order of `y` and `z` requires another `if` statement, so this becomes

>                if (x < y && x < z) {        // x comes first
>                    if (y < z)
>                       System.out.println( x + " " + y + " " + z );
>                    else
>                       System.out.println( x + " " + z + " " + y );
>                }
>                else if (x > y && x > z) {   // x comes last
>                    if (y < z)
>                       System.out.println( y + " " + z + " " + x );
>                    else
>                       System.out.println( z + " " + y + " " + x );
>                }
>                else {                       // x in the middle
>                    if (y < z)
>                       System.out.println( y + " " + x + " " + z);
>                    else
>                       System.out.println( z + " " + x + " " + y);
>                }

> You might check that this code will work correctly even if some of the values are the same. If the values of two variables are the same, it doesn't matter which order you print them in.

> Note, by the way, that even though you can say in English "if x is less than y and z,", you can't say in Java "`if (x < y && z)`". The `&&` operator can only be used between boolean values, so you have to make separate tests, `x<y` and `x<z`, and then combine the two tests with `&&`.

> There is an alternative approach to this problem that begins by asking, "which order should `x` and `y` be printed in?" Once that's known, you only have to decide where to stick in `z`. This line of thought leads to different Java code:

>                 if ( x < y ) {  // x comes before y
>                    if ( z < x )
>                       System.out.println( z + " " + x + " " + y);
>                    else if ( z > y )
>                       System.out.println( x + " " + y + " " + z);
>                    else
>                       System.out.println( x + " " + z + " " + y);
>                 }
>                 else {          // y comes before x
>                    if ( z < y )
>                       System.out.println( z + " " + y + " " + x);
>                    else if ( z > x )
>                       System.out.println( y + " " + x + " " + z);
>                    else
>                       System.out.println( y + " " + z + " " + x);
>                 }

> Once again, we see how the same problem can be solved in many different ways. The two approaches to this problem have not exhausted all the possibilities. For example, you might start by testing whether `x` is greater than `y`. If so, you could swap their values. Once you've done that, you know that `x` should be printed before `y`.

> Finally, let's write a complete program that uses an `if` statement in an interesting way. I want a program that will convert measurements of length from one unit of measurement to another, such as miles to yards or inches to feet. So far, the problem is extremely under-specified. Let's say that the program will only deal with measurements in inches, feet, yards, and miles. It would be easy to extend it later to deal with other units. The user will type in a measurement in one of these units, such as "17 feet" or "2.73 miles". The output will show the length in terms of each of the four units of measure. (This is easier than asking the user which units to use in the output.) An outline of the process is

>                Read the user's input measurement and units of measure
>                Express the measurement in inches, feet, yards, and miles
>                Display the four results

> The program can read both parts of the user's input from the same line by using `TextIO.getDouble()` to read the numerical measurement and `TextIO.getlnWord()` to read the units of measure. The conversion into different units of measure can be simplified by first converting the user's input into inches. From there, it can be converted into feet, yards, and miles. We still have to test the input to determine which unit of measure the user has specified:

>             Let measurement = TextIO.getDouble()
>             Let units = TextIO.getlnWord()
>             if the units are inches
>                Let inches = measurement
>             else if the units are feet
>                Let inches = measurement * 12         // 12 inches per foot
>             else if the units are yards
>                Let inches = measurement * 36         // 36 inches per yard
>             else if the units are miles
>                Let inches = measurement * 12 * 5280  // 5280 feet per mile
>             else
>                The units are illegal!
>                Print an error message and stop processing
>             Let feet = inches / 12.0
>             Let yards = inches / 36.0
>             Let miles = inches / (12.0 * 5280.0)
>             Display the results

> Since `units` is a `String`, we can use `units.equals("inches")` to check whether the specified unit of measure is "inches". However, it would be nice to allow the units to be specified as "inch" or abbreviated to "in". To allow these three possibilities, we can check `if (units.equals("inches") || units.equals("inch") || units.equals("in"))`. It would also be nice to allow upper case letters, as in "Inches" or "IN". We can do this by converting `units` to lower case before testing it or by substituting the function `units.equalsIgnoreCase` for `units.equals`.

> In my final program, I decided to make things more interesting by allowing the user to enter a whole sequence of measurements. The program will end only when the user inputs 0. To do this, I just have to wrap the above algorithm inside a `while` loop, and make sure that the loop ends when the user inputs a 0. Here's the complete program, followed by an applet that simulates it.

>        public class LengthConverter {

>           /* This program will convert measurements expressed in inches,
>              feet, yards, or miles into each of the possible units of
>              measure.  The measurement is input by the user, followed by
>              the unit of measure.  For example:  "17 feet", "1 inch",
>              "2.73 mi".  Abbreviations in, ft, yd, and mi are accepted.
>              The program will continue to read and convert measurements
>              until the user enters an input of 0.
>           */

>           public static void main(String[] args) {

>              double measurement;  // Numerical measurement, input by user.
>              String units;        // The unit of measure for the input, also
>                                   //    specified by the user.

>              double inches, feet, yards, miles;  // Measurement expressed in
>                                                  //   each possible unit of
>                                                  //   measure.

>              TextIO.putln("Enter measurements in inches, feet, yards, or miles.");
>              TextIO.putln("For example:  1 inch    17 feet    2.73 miles");
>              TextIO.putln("You can use abbreviations:   in   ft  yd   mi");
>              TextIO.putln("I will convert your input into the other units");
>              TextIO.putln("of measure.");
>              TextIO.putln();

>              while (true) {

>                 /* Get the user's input, and convert units to lower case. */

>                 TextIO.put("Enter your measurement, or 0 to end:  ");
>                 measurement = TextIO.getDouble();
>                 if (measurement == 0)
>                    break;  // terminate the while loop
>                 units = TextIO.getlnWord();
>                 units = units.toLowerCase();

>                 /* Convert the input measurement to inches. */

>                 if (units.equals("inch") || units.equals("inches")
>                                                 || units.equals("in")) {
>                     inches = measurement;
>                 }
>                 else if (units.equals("foot") || units.equals("feet")
>                                                 || units.equals("ft")) {
>                     inches = measurement * 12;
>                 }
>                 else if (units.equals("yard") || units.equals("yards")
>                                                  || units.equals("yd")) {
>                     inches = measurement * 36;
>                 }
>                 else if (units.equals("mile") || units.equals("miles")
>                                                    || units.equals("mi")) {
>                     inches = measurement * 12 * 5280;
>                 }
>                 else {
>                     TextIO.putln("Sorry, but I don't understand \""
>                                                          + units + "\".");
>                     continue;  // back to start of while loop
>                 }

>                 /* Convert measurement in inches to feet, yards, and miles. */

>                 feet = inches / 12;
>                 yards = inches / 36;
>                 miles = inches / (12*5280);

>                 /* Output measurement in terms of each unit of measure. */

>                 TextIO.putln();
>                 TextIO.putln("That's equivalent to:");
>                 TextIO.put(inches, 15);
>                 TextIO.putln(" inches");
>                 TextIO.put(feet, 15);
>                 TextIO.putln(" feet");
>                 TextIO.put(yards, 15);
>                 TextIO.putln(" yards");
>                 TextIO.put(miles, 15);
>                 TextIO.putln(" miles");
>                 TextIO.putln();

>              } // end while

>              TextIO.putln();
>              TextIO.putln("OK!  Bye for now.");

>           } // end main()

>        } // end class LengthConverter

> (Applet "LengthConverterConsole" would be displayed here
> if Java were available.)

[ Next Section | Previous Section | Chapter Index | Main Index ]