Selection Statements – Control Flow

4.1 Selection Statements

Java provides selection statements that allow the program to choose between alternative actions during execution. The choice is based on criteria specified in the selection statement. These selection statements are

  • The simple if statement
  • The if-else statement
  • The switch statement and the switch expression

The Simple if Statement

The simple if statement has the following syntax:

if (
condition
)
statement

It is used to decide whether an action is to be performed or not, based on a condition. The action to be performed is specified by statement, which can be a single statement or a code block. The condition must evaluate to a boolean or Boolean value. In the latter case, the Boolean value is unboxed to the corresponding boolean value.

The semantics of the simple if statement are straightforward. The condition is evaluated first. If its value is true, statement (called the if block) is executed and then execution continues with the rest of the program. If the value is false, the if block is skipped and execution continues with the rest of the program. The semantics are illustrated by the activity diagram in Figure 4.1a.

Figure 4.1 Activity Diagram for if Statements

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

Click here to view code image

if (emergency)            // emergency is a boolean variable
  operate();
if (temperature > critical)
  soundAlarm();
if (isLeapYear() && endOfCentury())
  celebrate();
if (catIsAway()) {        // Block
  getFishingRod();
  goFishing();
}

Note that statement can be a block, and the block notation is necessary if more than one statement is to be executed when the condition is true.

Since the condition evaluates to a boolean value, it avoids a common programming error: using an expression of the form (a=b) as the condition, where inadvertently an assignment operator is used instead of a relational operator. The compiler will flag this as an error, unless both a and b are boolean.

Note that the if block can be any valid statement. In particular, it can be the empty statement (;) or the empty block ({}). A common programming error is inadvertent use of the empty statement.

Click here to view code image

if (emergency); // Empty if block
  operate();    // Executed regardless of whether it was an emergency

Variable Arity and Fixed Arity Method Calls – Declarations

Variable Arity and Fixed Arity Method Calls

The calls at (1) to (4) in Example 3.15 are all variable arity calls, as an implicit Object array is created in which the values of the actual parameters are stored. The reference value of this array is passed to the method. The printout shows that the type of the parameter is actually an array of Objects ([Ljava.lang.Object;).

The call at (6) differs from the previous calls in that the actual parameter is an array that has the same type (Object[]) as the variable arity parameter, without having to create an implicit array. In such a case, no implicit array is created, and the reference value of the array dateInfo is passed to the method. See also the result from this call at (6) in the output. The call at (6) is a fixed arity call (also called a non-varargs call), where no implicit array is created:

Click here to view code image

flexiPrint(dateInfo);              // (6) Non-varargs call

However, if the actual parameter is cast to the type Object as at (7), a variable arity call is executed:

Click here to view code image

flexiPrint((Object) dateInfo);     // (7) new Object[] {(Object) dateInfo}

The type of the actual argument (Object) is now not the same as that of the variable arity parameter (Object[]), resulting in an array of the type Object[] being created in which the array dateInfo is stored as an element. The printout at (7) shows that only the text representation of the dateInfo array is printed, and not its elements, as it is the sole element of the implicit array.

The call at (8) is a fixed arity call, for the same reason as the call at (6). Now, however, the array dateInfo is explicitly stored as an element in an array of the type Object[] that matches the type of the variable arity parameter:

Click here to view code image

flexiPrint(new Object[]{dateInfo});// (8) Non-varargs call

The output from (8) is the same as the output from (7), where the array dateInfo was passed as an element in an implicitly created array of type Object[].

The compiler issues a warning for the call at (9):

Click here to view code image

flexiPrint(args);                  // (9) Warning!

The actual parameter args is an array of the type String[], which is a subtype of Object[]—the type of the variable arity parameter. The array args can be passed in a fixed arity call as an array of the type String[], or in a variable arity call as an element in an implicitly created array of the type Object[]. Both calls are feasible and valid in this case. Note that the compiler chooses a fixed arity call rather than a variable arity call, but also issues a warning. The result at (9) confirms this course of action. A warning at compile time is not the same as a compile-time error. The former does not prevent the program from being run, whereas the latter does.

At (10), the array args of the type String[] is explicitly passed as an Object in a variable arity call, similar to the call at (7):

Click here to view code image

flexiPrint((Object) args);         // (10) Explicit varargs call

At (11), the array args of type String[] is explicitly passed as an array of the type Object[] in a fixed arity call. This call is equivalent to the call at (9), where the widening reference conversion is implicit, but now without a warning at compile time. The two calls print the same information, as is evident from the output at (9) and (11):

Click here to view code image

flexiPrint((Object[]) args);       // (11) Explicit non-varargs call