Transfer Statements – Control Flow

Transfer Statements – Control Flow

4.9 Transfer Statements

Java provides the following language constructs for transferring control in a program:

  • The yield statement (p. 164)
  • The break statement
  • The continue statement
  • The return statement

The throw statement can also transfer control in a program (§7.4, p. 386).

4.10 Labeled Statements

A statement may have a label:

label
 :
statement

A label is any valid identifier; it always immediately precedes the statement. Label names exist in their own namespace, so that they do not conflict with names of packages, classes, interfaces, methods, fields, and local variables. The scope of a label is the statement prefixed by the label, meaning that it cannot be redeclared as a label inside the labeled statement—analogous to the scope of local variables.

Click here to view code image

L1: if (i > 0) {
  L1: System.out.println(i);    // (1) Not OK. Label L1 redeclared.
}
L1: while (i < 0) {             // (2) OK.
  L2: System.out.println(i);
}
L1: {                           // (3) OK. Labeled block.
  int j = 10;
  System.out.println(j);
}
L1: try {                       // (4) OK. Labeled try-catch-finally block.
  int j = 10, k = 0;
  L2: System.out.println(j/k);
} catch (ArithmeticException ae) {
  L3: ae.printStackTrace();
} finally {
  L4: System.out.println(“Finally done.”);
}

A statement can have multiple labels:

Click here to view code image

LabelA: LabelB: System.out.println(“Multiple labels. Use judiciously.”);

A declaration statement cannot have a label:

Click here to view code image

L0: int i = 0;                  // Compile-time error!

A labeled statement is executed as if it were unlabeled, unless it is the break or continue statement. This behavior is discussed in the next two subsections.

4.11 The break Statement

The break statement comes in two forms: unlabeled and labeled.

Click here to view code image

break;             // the unlabeled form
break label;        // the labeled form

The unlabeled break statement terminates loops (for(;;), for(:), while, do-while) and switch statements, and transfers control out of the current context (i.e., the closest enclosing block). The rest of the statement body is skipped, and execution continues after the enclosing statement.

In Example 4.10, the break statement at (1) is used to terminate a for(;;) loop. Control is transferred to (2) when the value of i is equal to 4 at (1), skipping the rest of the loop body and terminating the loop.

Example 4.10 also shows that the unlabeled break statement terminates only the innermost loop or switch statement that contains the break statement. The break statement at (3) terminates the inner for(;;) loop when j is equal to 2, and execution continues in the outer switch statement at (4) after the for(;;) loop.

Example 4.10 The break Statement

Click here to view code image

class BreakOut {
  public static void main(String[] args) {
    System.out.println(“i    sqrt(i)”);
    for (int i = 1; i <= 5; ++i) {
      if (i == 4)
        break;                              // (1) Terminate loop. Control to (2).
      // Rest of loop body skipped when i gets the value 4.
      System.out.printf(“%d    %.2f%n”, i, Math.sqrt(i));
    } // end for
    // (2) Continue here.
    int n = 2;
    switch (n) {
      case 1:
        System.out.println(n);
        break;
      case 2:
        System.out.println(“Inner for(;;) loop: “);
        for (int j = 0; j <= n; j++) {
          if (j == 2)
            break;                          // (3) Terminate loop. Control to (4).
          System.out.println(“j = ” + j);
        }
      default:
        System.out.println(“default: n = ” + n); // (4) Continue here.
    }
  }
}

Output from the program:

Click here to view code image

i    sqrt(i)
1    1.00
2    1.41
3    1.73
Inner for(;;) loop:
j = 0
j = 1
default: n = 2

A labeled break statement can be used to terminate any labeled statement that contains the break statement. Control is then transferred to the statement following the enclosing labeled statement. In the case of a labeled block, the rest of the block is skipped and execution continues with the statement following the block:

Click here to view code image

out:                        // Label.
{                           // (1) Labeled block.
  // …
  if (j == 10) break out;   // (2) Terminate block. Control to (3).
  System.out.println(j);    // Rest of the block not executed if j == 10.
  // …
}
// (3) Continue here.

In Example 4.11, the program continues to add the elements below the diagonal of a square matrix until the sum is greater than 10. Two nested for loops are defined at (1) and (2). The outer loop is labeled outer at (1). The unlabeled break statement at (3) transfers control to (5) when it is executed; that is, it terminates the inner loop and control is transferred to the statement after the inner loop. The labeled break statement at (4) transfers control to (6) when it is executed; that is, it terminates both the inner and outer loops, transferring control to the statement after the loop labeled outer.

Example 4.11 Labeled break Statement

Click here to view code image

class LabeledBreakOut {
  public static void main(String[] args) {
    int[][] squareMatrix = {{4, 3, 5}, {2, 1, 6}, {9, 7, 8}};
    int sum = 0;
    outer: for (int i = 0; i < squareMatrix.length; ++i){   // (1) label
        for (int j = 0; j < squareMatrix[i].length; ++j) {  // (2)
          if (j == i) break;         // (3) Terminate inner loop. Control to (5).
          System.out.println(“Element[” + i + “, ” + j + “]: ” +
                              squareMatrix[i][j]);
          sum += squareMatrix[i][j];
          if (sum > 10) break outer; // (4) Terminate both loops. Control to (6).
        } // end inner loop
        // (5) Continue with update expression in the outer loop header.
      } // end outer loop
    // (6) Continue here.
    System.out.println(“sum: ” + sum);
  }
}

Output from the program: Element[1, 0]: 2
Element[2, 0]: 9
sum: 11