Previous Table of Contents Next


14.2.12.4. Labeled break and continue Statements

The break and continue statements, used alone, behave the same in Java as they do in C. However, in Java, they may optionally be followed by a label that specifies an enclosing loop (for continue) or any enclosing statement (for break). The labeled forms of these statements allow you to “break” and “continue” any specified statement or loop within a method definition, not only the nearest enclosing statements or loop.

The break statement, without a label, transfers control out of (“breaks out of” or terminates) the nearest enclosing for, while, do, or switch statement, exactly as in C. If the break keyword is followed by an identifier that is the label of an arbitrary enclosing statement, execution transfers out of that enclosing statement. After the break statement is executed, any required finally clauses are executed, and control resumes at the statement following the terminated statement. (The finally clause and the try statement it is associated with are exception handling constructs and are explained in the next section.) For example:

   test: if (check(i)) {
       try {
           for(int j=0; j < 10; j++) {
               if (j > i) break;          // Terminate just this loop.
               if (a[i][j] =\^= null)
                   break test;            // Do the finally clause and
           }                              // terminate the if statement.
       }
       finally { cleanup(a, i, j); }
   }

Without a label, the continue statement works exactly as in C: It stops the iteration in progress and causes execution to resume after the last statement in the while, do, or for loop, just before the loop iteration is to begin again. If the continue keyword is followed by an identifier that is the label of an enclosing loop, execution skips to the end of that loop instead. If there are any finally clauses between the continue statement and the end of the appropriate loop, these clauses are executed before control is transferred to the end of the loop.

The following code fragment illustrates how the continue statement works in its labeled and unlabeled forms.

   big_loop: while(!done) {
       if (test(a,b) =\^= 0) continue;       // Control goes to point 2.
       try {
           for(int i=0; i < 10; i++) {
               if (a[i] =\^= null)
                   continue;                // Control goes to point 1.
               else if (b[i] =\^= null)
                   continue big_loop;       // Control goes to point 2,
                                            // after executing the
                                            // finally block.
               doit(a[i],b[i]);
              // Point 1. Increment and start loop again with the test.
           }
       }
       finally { cleanup(a,b); }
       // Point 2. Start loop again with the (!done) test.
   }

Note the non-intuitive feature of the labeled continue statement: The loop label must appear at the top of the loop, but continue causes execution to transfer to the very bottom of the loop.

14.2.12.5. No goto Statement

goto is a reserved word in Java, but the goto statement is not currently part of the language. Labeled break and continue statements replace some important and legitimate uses of goto, and the try/catch/finally statement replaces the others.

14.2.12.6. The synchronized Statement

Since Java is a multithreaded system, care must often be taken to prevent multiple threads from modifying objects simultaneously in a way that might leave the object’s state corrupted. Sections of code that must not be executed simultaneously are known as “critical sections.” Java provides the synchronized statement to protect these critical sections. The syntax is:

   synchronized (expression) statement

expression is an expression that must resolve to an object or an array. The statement is the code of the critical section, which is usually a block of statements (within { and }). The synchronized statement attempts to acquire an exclusive lock for the object or array specified by expression. It does not execute the critical section of code until it can obtain this lock, and in this way, ensures that no other threads can be executing the section at the same time.

Note that you do not have to use the synchronized statement unless your program creates multiple threads that share data. If only one thread ever accesses a data structure, there is no need to protect it with synchronized. When you do have to use it, it might be in code like the following:

   public static void SortIntArray(int[] a) {
       // Sort the array a. This is synchronized so that some other
       // thread can’t change elements of the array while we’re
       // sorting it.
       // At least not other threads that protect their changes to the
       // array with synchronized.
       synchronized (a) {
           // do the array sort here.
       }
   }

The synchronized keyword is more often used as a method modifier in Java. When applied to a method, it indicates that the entire method is a critical section. For a synchronized class method (a static method), Java obtains an exclusive lock on the class before executing the method. For a synchronized instance method, Java obtains an exclusive lock on the class instance. (Class methods and instance methods are discussed in the next section.)


Previous Table of Contents Next