The if-else Statement – Control Flow

The if-else Statement

The if-else statement is used to decide between two actions, based on a condition. It has the following syntax:

if (
condition
)
statement
1
else
statement
2

The condition is evaluated first. If its value is true (or unboxed to true), statement1 (the if block) is executed and then execution continues with the rest of the program. If the value is false (or unboxed to false), statement2 (the else block) is executed and then execution continues with the rest of the program. In other words, one of two mutually exclusive actions is performed. The else clause is optional; if omitted, the construct is equivalent to the simple if statement. The semantics are illustrated by the activity diagram in Figure 4.1b.

In the following examples of the if-else statement, it is assumed that all variables and methods have been appropriately defined:

Click here to view code image

if (emergency)
  operate();
else
  joinQueue();
if (temperature > critical)
  soundAlarm();
else
  businessAsUsual();
if (catIsAway()) {
  getFishingRod();
  goFishing();
} else
  playWithCat();

Since actions can be arbitrary statements, the if statements can be nested.

Click here to view code image

if (temperature >= upperLimit) {        // (1)
  if (danger)                           // (2) Simple if.
    soundAlarm();
  if (critical)                         // (3)
    evacuate();
  else                                  // Goes with if at (3).
    turnHeaterOff();
} else                                  // Goes with if at (1).
    turnHeaterOn();

The use of block notation, {}, can be critical to the execution of if statements. The if statements (A) and (B) in the following examples do not have the same meaning. The if statements (B) and (C) are the same, with extra indentation used in (C) to make the meaning evident. Leaving out the block notation in this case could have catastrophic consequences: The heater could be turned on when the temperature is above the upper limit.

Click here to view code image

// (A):
if (temperature > upperLimit) {          // (1) Block notation.
  if (danger) soundAlarm();              // (2)
} else                                   // Goes with if at (1).
  turnHeaterOn();
// (B):
if (temperature > upperLimit)            // (1) Without block notation.
  if (danger) soundAlarm();              // (2)
else turnHeaterOn();                     // Goes with if at (2).
// (C):
if (temperature > upperLimit)            // (1)
  if (danger)                            // (2)
    soundAlarm();
  else                                   // Goes with if at (2).
    turnHeaterOn();

The rule for matching an else clause is that an else clause always refers to the nearest if that is not already associated with another else clause. Block notation and proper indentation can be used to make the meaning obvious.

Cascading of if-else statements comprises a sequence of nested if-else statements where the if block of the next if-else statement is joined to the else clause of the previous if-else statement. The decision to execute a block is then based on all the conditions evaluated so far.

Click here to view code image

if (temperature >= upperLimit) {                           // (1)
  soundAlarm();
  turnHeaterOff();
} else if (temperature < lowerLimit) {                     // (2)
  soundAlarm();
  turnHeaterOn();
} else if (temperature == (upperLimit-lowerLimit)/2) {     // (3)
  doingFine();
} else                                                     // (4)
  noCauseToWorry();

The block corresponding to the first if condition that evaluates to true is executed, and the remaining if statements are skipped. In the preceding example, the block at (3) will execute only if the conditions at (1) and (2) are false and the condition at (3) is true. If none of the conditions is true, the block associated with the last else clause is executed. If there is no last else clause, no actions are performed.

Calling a Variable Arity Method – Declarations

Calling a Variable Arity Method

Example 3.15 illustrates various aspects of calling a variable arity method. The method flexiPrint() in the VarargsDemo class has a variable arity parameter:

Click here to view code image

public static void flexiPrint(Object… data) { // Object[]
  //…
}

The variable arity method prints the name of the Class object representing the actual array that is passed at runtime. It prints the number of elements in this array as well as the text representation of each element in the array.

The method flexiPrint() is called in the main() method. First it is called with the values of primitive types and Strings ((1) to (8)), and then it is called with the program arguments (p. 141) supplied on the command line ((9) to (11)).

Compiling the program results in a warning at (9), which we ignore for the time being. The program can still be run, as shown in Example 3.15. The numbers at the end of the lines in the output relate to numbers in the code, and are not printed by the program.

Example 3.15 Calling a Variable Arity Method

Click here to view code image

public class VarargsDemo {
  public static void flexiPrint(Object… data) { // Object[]
    // Print the name of the Class object for the varargs parameter.
    System.out.print(“Type: ” + data.getClass().getName());
    System.out.println(”  No. of elements: ” + data.length);
    System.out.print(“Element values: “);
    for(Object element : data)
      System.out.print(element + ” “);
    System.out.println();
  }
  public static void main(String… args) {
    int    day       = 13;
    String monthName = “August”;
    int    year      = 2009;
    // Passing primitives and non-array types:
    flexiPrint();                      // (1) new Object[] {}
    flexiPrint(day);                   // (2) new Object[] {Integer.valueOf(day)}
    flexiPrint(day, monthName);        // (3) new Object[] {Integer.valueOf(day),
                                       //                   monthName}
    flexiPrint(day, monthName, year);  // (4) new Object[] {Integer.valueOf(day),
                                       //                   monthName,
                                       //                   Integer.valueOf(year)}
    System.out.println();
    // Passing an array type:
    Object[] dateInfo = {day,          // (5) new Object[] {Integer.valueOf(day),
                         monthName,    //                   monthName,
                         year};        //                   Integer.valueOf(year)}
    flexiPrint(dateInfo);              // (6) Non-varargs call
    flexiPrint((Object) dateInfo);     // (7) new Object[] {(Object) dateInfo}
    flexiPrint(new Object[]{dateInfo});// (8) Non-varargs call
    System.out.println();
    // Explicit varargs or non-varargs call:
    flexiPrint(args);                  // (9) Warning!
    flexiPrint((Object) args);         // (10) Explicit varargs call
    flexiPrint((Object[]) args);       // (11) Explicit non-varargs call
  }
}

Compiling the program:

Click here to view code image

>
javac VarargsDemo.java
VarargsDemo.java:41: warning: non-varargs call of varargs method with inexact
argument type for last parameter;
    flexiPrint(args);                  // (9) Warning!
               ^
  cast to Object for a varargs call
  cast to Object[] for a non-varargs call and to suppress this warning
1 warning

Running the program:

Click here to view code image

>
java VarargsDemo To arg or not to arg

Type: [Ljava.lang.Object;  No. of elements: 0                (1)
Element values:
Type: [Ljava.lang.Object;  No. of elements: 1                (2)
Element values: 13
Type: [Ljava.lang.Object;  No. of elements: 2                (3)
Element values: 13 August
Type: [Ljava.lang.Object;  No. of elements: 3                (4)
Element values: 13 August 2009
Type: [Ljava.lang.Object;  No. of elements: 3                (6)
Element values: 13 August 2009
Type: [Ljava.lang.Object;  No. of elements: 1                (7)
Element values: [Ljava.lang.Object;@1eed786
Type: [Ljava.lang.Object;  No. of elements: 1                (8)
Element values: [Ljava.lang.Object;@1eed786
Type: [Ljava.lang.String;  No. of elements: 6                (9)
Element values: To arg or not to arg
Type: [Ljava.lang.Object;  No. of elements: 1                (10)
Element values: [Ljava.lang.String;@187aeca
Type: [Ljava.lang.String;  No. of elements: 6                (11)
Element values: To arg or not to arg