3.5 Nested if Statements

We have seen that we can use if statements to choose between two alternatives. Frequently, however, we want to choose from among more than two possibilities.

Example 1

If we want to write a statement based on the sign of a variable x, we could write three if statements.

if (x < 0)
     System.out.println("value is negative");
if (x > 0)
     System.out.println("value is positive");
if (x == 0)
     System.out.println("value is zero"); 

For any value of x, this solution involves three tests. We can increase the efficiency of the code by nesting the statements. This involves placing one if statement within another as shown in the next example.

Example 2

This improves the efficiency of the code in Example 1.

if (x < 0)
   System.out.println("value is negative");
else
   if (x > 0)
      System.out.println("value is positive");
   else
      System.out.println("value is zero") ;
 
Now, if x is negative, only one test is performed while if x is positive or zero, only two tests are performed. In no case is it necessary to perform three tests.
 

In the next example nesting is used in a slightly more complex way.

Example 3

The if statement shown below efficiently determines the largest among three values x, y, and z and assigns this value to largest.

if (x >= y)
   // y eliminated - largest must be either x or z
   if (x >= z)
      largest = x;
   else
      largest = z;
else 
   // x eliminated - largest must be either y or z
   if (y >= z)
      largest = y;
   else
      largest = Z;
      
There are many other ways that we could determine the largest of three values but the one shown here involves the least work. 


In the examples that we have shown so far, we have been following the same indentation pattern that we introduced at the beginning of this chapter, aligning corresponding if's and else's and indenting two spaces past them for statements nested inside the if. If we have a long sequence of nested if statements, the resulting indentation can become excessive, leaving us little room on a line for our statements. To overcome this, we sometimes vary our indentation pattern.

Example 4

This statement prints a comment that depends on the value of the char variable grade.

 if (grade =='A')
   System.out.println("Excellent");
else if (grade == 'B')
   System.out.println("Good");
else if (grade == 'C')
   System.out.println("Average");
else if (grade == 'D')
   System.out.println("Fair");
else if (grade == 'E')
   System.out.println("Poor");
else
   System.out.println("Invalid grade");
   
As well as noting the indentation style, note that the last line covers the
case of an invalid grade. You should always be sure that your code covers
such possibilities. 

A problem arises with nested if statements when one of the if statements has no else clause. The following segments illustrate the problem.

A:    if (p)
         if (q)
            System.out.println("Path A-1");
         else
            System.out.println("Path A-2");
 
B:    if (p)
         if (q)
            System.out.println("Path B-1");
         else
            System.out.println("Path B-2"); 

The indentation in segment A indicates that the else clause is associated with the second if. The indentation in segment B indicates that the else clause is associated with the first if. Since indentation is ignored by the computer, the two segments have the same structure. The problem of deciding which interpretation is correct is called the dangling else problem. In Java, interpretation A is the correct one. The general rule is to associate an else with the nearest available preceding if. If we want to have the else associated with the first if, the preferred solution is to use brace brackets to "close off" the second if as shown in the next segment.

B*:if (p)
   {
      if (q)
         System.out.println("Path 1");
   }
   else
      System.out.println ("Path 2"); 

An empty statement provides an alternative solution to the problem.

B**: if (p)
       if (q)
         System.out.println("Path 1");
      else
         ; // to "close off" the second if
      else
         System.out.println("Path 2");
 

Exercise 3.5

  1. Simplify the following sequence by nesting so that the effect is the same but fewer comparisons are required.
if (temperature > maxTemp)
   System.out.println("Porridge too hot");
if (temperature < minTemp)
   System.out.println("Porridge too cold");
if (temperature >= minTemp && temperature <= maxTemp)
   System.out.println("Porridge just right!"); 
  1. Consider the following statement.
  if (age < minAge)
      if (income > minIncome)
         System.out.println("Accept");
      else
         System.out.println("Reject"); 

What will the statement print if

    1. age > minAge and income < minIncome?
    2. age < minAge and income < minIncome?
  1. Using nested if statements, write a single statement that prints the smallest value contained in the variables a, b, and c.
  2. Write a statement that, if the value of the variable item is negative, adds its value to negativeSum but, if it is positive, adds its value to positiveSum. If, on the other hand, the value of item is zero, the statement should simply increase the variable zeroCount by one.

5.      Assume that the following declarations have been made.

   int year;
   boolean isLeapYear; 

Write a fragment that will assign isLeapYear the value true if year represents a leap year and false otherwise. A year is usually a leap year if its number is a multiple of four. It is not a leap year, however, if its number is a multiple of 100 but not a multiple of 400. (As examples, 1900 was not a leap year but 2000 was a leap year.)