5.4 Transfer Statements

Java provides six language constructs for transferring control in a program:

  • break

  • continue

  • return

  • try-catch-finally

  • throw

  • assert

This section discusses the first three statements, and the remaining statements are discussed in subsequent sections.

Note that Java does not have a goto statement, although goto is a reserved word.

Labeled Statements

A statement may have a label.


<label> : <statement>

A label is any valid identifier and it always immediately proceeds the statement. Label names exist in their own name space, 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.

L1: if (i > 0) {
    L1: System.out.println(i);  // (1) Not OK. Label 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:

LabelA: LabelB: System.out.println("Mutliple labels. Use judiciously.");

A declaration statement cannot have a label:

L0: int i = 0;                  // Compile time error.

A labeled statement is executed like it was non-labeled, unless it contains the break or continue statements. This is discussed in the next two subsections.

break Statement

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

break;             // the unlabeled form

break <label>;     // the labeled form

The unlabeled break statement terminates loops (for, while, do-while) and switch statements which contain the break statement, and transfers control out of the current context (i.e., the closest enclosing block). The rest of the statement body is skipped, terminating the enclosing statement, with execution continuing after this statement.

In Example 5.4, 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 5.4 also shows that the unlabeled break statement only terminates 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 5.4 break Statement
class BreakOut {

    public static void main(String[] args) {

        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.println(i + "\t" + 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).
                        else
                            System.out.println(j);
            default: System.out.println("default: " + n); // (4) Continue here.
        }
    }
}

Output from the program:

1    1.0
2    1.4142135623730951
3    1.7320508075688772
Inner for loop:
0
1
default: 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:

out:
{                           // (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 5.5, 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 (i.e., it terminates both the inner and the outer loop, transferring control to the statement after the loop labeled outer).

Example 5.5 Labeled break Statement
class LabeledBreakOut {
    public static void main(String[] args) {
        int[][] squareMatrix = {{4, 3, 5}, {2, 1, 6}, {9, 7, 8}};
        int sum = 0;
        outer:                                                  // label
        for (int i = 0; i < squareMatrix.length; ++i){          // (1)
            for (int j = 0; j < squareMatrix[i].length; ++j) {  // (2)
                if (j == i) break;        // (3) Terminate this 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 outer loop.
        } // 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

continue Statement

Like the break statement, the continue statement also comes in two forms: the unlabeled and the labeled form.

continue;             // the unlabeled form
continue <label>;     // the labeled form

The continue statement can only be used in a for, while, or do-while loop to prematurely stop the current iteration of the loop body and proceed with the next iteration, if possible. In the case of the while and do-while loops, the rest of the loop body is skipped, that is, stopping the current iteration, with execution continuing with the <loop condition>. In the case of the for loop, the rest of the loop body is skipped, with execution continuing with the <increment expression>.

In Example 5.6, an unlabeled continue statement is used to skip an iteration in 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 continuing with the <increment expression> in the for statement.

Example 5.6 continue Statement
class Skip {
    public static void main(String[] args) {
        for (int i = 1; i <= 5; ++i) {
            if (i == 4) continue;             // (1) Control to (2).
            // Rest of loop body skipped when i has the value 4.
            System.out.println(i + "\t" + Math.sqrt(i));
            // (2). Continue with increment expression.
        } // end for
    }
}

Output from the program:

1       1.0
2       1.4142135623730951
3       1.7320508075688772
5       2.23606797749979

A labeled continue statement must occur within a labeled loop that has the same label. Execution of the labeled continue statement then transfers control to the end of that enclosing labeled loop. In Example 5.7, the unlabeled continue statement at (3) transfers control to (5) when it is executed; that is, the rest of the loop body is skipped and execution continues with the next iteration of the inner loop. The labeled continue statement at (4) transfers control to (6) when it is executed (i.e., it terminates the inner loop but execution continues with the next iteration of the loop labeled outer). It is instructive to compare the output from Example 5.5 (labeled break) and Example 5.7 (labeled continue).

Example 5.7 Labeled continue Statement
class LabeledSkip {
    public static void main(String[] args) {
        int[][] squareMatrix = {{4, 3, 5}, {2, 1, 6}, {9, 7, 8}};
        int sum = 0;
        outer:                                                  // label
        for (int i = 0; i < squareMatrix.length; ++i){          // (1)
            for (int j = 0; j < squareMatrix[i].length; ++j) {  // (2)
                if (j == i) continue;                   // (3) Control to (5).
                System.out.println("Element[" + i + ", " + j + "]: " +
                                    squareMatrix[i][j]);
                sum += squareMatrix[i][j];
                if (sum > 10) continue outer;           // (4) Control to (6).
                // (5) Continue with inner loop.
            } // end inner loop
            // (6) Continue with outer loop.
        } // end outer loop
        System.out.println("sum: " + sum);
    }
}

Output from the program:

Element[0, 1]: 3
Element[0, 2]: 5
Element[1, 0]: 2
Element[1, 2]: 6
Element[2, 0]: 9
sum: 25

return Statement

The return statement is used to stop execution of a method and transfer control back to the calling code (a.k.a. the caller). The usage of the two forms of the return statement is dictated by whether it is used in a void or a non-void method. The first form does not return any value to the calling code, but the second form does. Note that the keyword void does not represent any type.

The <expression> must evaluate to a primitive value or a reference value, and its type must be assignable to the return type in the method prototype (see Sections 3.4 and 6.6). As can be seen from Table 5.1, non-void methods must specify a return value using the return statement. A void method need not have a return statement ?in which case control normally returns to the caller after the last statement in the method's body has been executed. The first form of the return statement can also be used in constructors, as these also do not return a value. Example 5.8 illustrates the usage of the return statement summarized in Table 5.1.

Table 5.1. return Statement

Form of return Statement

In void Method

In Non-void Method

return;

optional

not allowed

return <expression>;

not allowed

mandatory

Example 5.8 The return Statement
public class ReturnDemo {

    public static void main (String[] args) { // (1) void method can use return.
        if (args.length == 0) return;
        output(checkValue(args.length));
    }

    static void output(int value) { // (2) void method need not use return.
        System.out.println(value);
        return 'a';                 // Not OK. Cannot return a value.
    }

    static int checkValue(int i) {  // (3) non-void method must return a value.
        if (i > 3)
           return i;                // OK.
        else
           return 2.0;              // Not OK. double not assignable to int.
    }
}