Incremental Java
break and continue

Loop Body

Running a loop body is normally just following the rules of control flow. The only way to exit a loop, in the usual circumstances is for the loop condition to evaluate to false.

There are however, two control flow statements that allow you to change the control flow.

Enclosing Loop

Let's define an enclosing loop.

The enclosing loop of a statement is the loop (or loops) in which a statement is in its loop body.

For example:

while ( j < k )  // LOOP 1
{
   j++ ;
}
while ( i < 0 )  // LOOP 2
{
   statement ;
}
do  // LOOP 3
{
   j++ ;
} while  ( j < k ) ;
The enclosing loop of statement is LOOP 2. That's because it's in LOOP 2's loop body. Neither LOOP 1 nor LOOP 3 are the enclosing loop for statement.

Here's the simple test:

If statement appears in the loop body of LOOP. Then, LOOP is an enclosing loop of statement.
statement can have more than one enclosing loops.
while ( i < 0 )  // LOOP 1
{
   while ( j < k )  // LOOP 2
   {
      statement ;
      j++ ;
   }
}
In this example, statement has two enclosing loops. It's in the loop body of LOOP 1 andLOOP 2, so both LOOP 1 and LOOP 2 are the enclosing loops of statement.

If a statement has more than one enclosing loop, then these enclosing loops must be nested in one another. This makes sense, if you think about it.

If we make a small change to the code:

while ( i < 0 )  // LOOP 1
{
   statement ;
   while ( j < k )  // LOOP 2
   {
      j++ ;
   }
}
The enclosing loop for statement is just LOOP 1. LOOP 2 is no longer an enclosing loop because we're not in the loop body of LOOP 2, as in the previous example.

We use enclosing loops to explain how break and continue work.

Innermost Enclosing Loop

We define the innermost enclosing loop of statement as the loop that has the fewest number of lines, which includes the statement in its loop body. In other words, if a statement has more than one enclosing loop, then pick the innermost loop. That's the innermost enclosing loop.

while ( i < 0 )  // LOOP 1
{
   while ( j < k )  // LOOP 2
   {
      statement ;
      j++ ;
   }
}
The innermost enclosing loop of statement is LOOP 2. LOOP 1 is an enclosing loop as well, but it's not the innermost enclosing loop.

Here's another example:

while ( i < 0 )  // LOOP 1
{
   statement ;
   while ( j < k )  // LOOP 2
   {
      j++ ;
   }
}
In this example, the innermost enclosing loop of statement is LOOP 1. It isn't LOOP 2 because LOOP 2 is not even an enclosing loop of statement!

We say innermost enclosing loop, even if there is only one enclosing loop. In that case, the only enclosing loop is the innermost enclosing loop.

I know we've spent a great deal of time explaining this concept, but it should make it easier for you to follow the rest of the explanation.

Notice each statement may have a different enclosing loop.

break

Let's see how break works.
public void twoNum( int num, int val )
{
  for ( int i = 0 ; i < num ; i++ )
  {
     if ( num >= 2 * val )
        break ;
     val = val / 2 ;
  }
  // break comes here if it runs
}
A break statement, if executed, jumps out of the innermost enclosing loop of the statement.

In general, you can only break out of a single loop (namely, the innermost enclosing loop of the break statement). For example

public void twoNum( int num, int val )
{
  for ( int i = 0 ; i < num ; i++ )
  {
      for ( int j = 0 ; j < num ; j++ )
      {
         if ( i + j >= 2 * val )
            break ;
         val = val / 2 ;
      }
      // break comes here if it runs
   }
}
Java has made break more powerful. Sometimes you want to break out of more than one loop.

Label

You can put a label at the start of a loop. A label is an identifier, followed by a colon. It's just a location in your code. You can then use break followed by the label name to break out of the loop with the label by it.
public void twoNum( int num, int val )
{
OUTER_LOOP: // OUTER_LOOP is a label
  for ( int i = 0 ; i < num ; i++ )
  {
      for ( int j = 0 ; j < num ; j++ )
      {
         if ( i + j >= 2 * val )
            break OUTER_LOOP ;
         val = val / 2 ;
      }
  }
  // break comes here if it runs
}
OUTER_LOOP is a label that's placed just before a loop.

When you write:

  break OUTER_LOOP ;
the label, OUTER_LOOP, must be a label for an enclosing loop. Usually, this is not the innermost enclosing loop since we can just use a plain break statement, instead of a "break with a label".

The label must be before a enclosing loop of the break statement.

The following is illegal

public void twoNum( int num, int val )
{
LOOP:
  for ( int i = 0 ; i < num ; i++ )
  {
     sum += i ;
  }

  for ( int j = 0 ; j < num ; j++ )
  {
     if ( i + j >= 2 * val )
         break LOOP ; // ILLEGAL. LOOP not an enclosing loop
     val = val / 2 ;
  }
}
This is illegal. The label LOOP labels a for loop. But this loop is not an enclosing loop for the statement, break LOOP. You can't break out of a loop that's not enclosing the break statement.

You don't break out of if

In the code above, you see a break in an if body. break can only exit out of an enclosing loop or an enclosing switch statement (same idea as an enclosing loop, but it's a switch statement).

If a break statement appears in an if body, just ignore the if. Find the innermost enclosing loop or innermost switch statement. Pick the innermost of the two, and then exit out of the loop or switch statement, whichever is innermost.

A break statement must appear in a loop body or a body of a switch statement, otherwise the code won't compile.

Works with Other Loops

Even though we used for loops in all of our examples, break works the same way with while and do-while loops. It changes the control flow to the point just after the loop.

continue

Intuitively, continue says "go to the next iteration of the loop". A continue statement must appear in a loop body, or it won't compile.

If the innermost enclosing loop of a continue statement is a while or do-while loop, then running a continue statement causes control flow to jump to the cond of the innermost enclosing loop. If the innermost enclosing loop is a for loop, continue jumps to the update of that loop.

The continue statement causes control flow to go to the next iteration of the loop, skipping over the remainder of the loop body.

Consider this example:

while ( i != 3 )  // continue jumps here
{
   if ( i > num )
      continue ; // Jumps to condition, i != 3
   System.out.println( "Here I am!" ) ;
}
If the continue statement runs, then it causes control flow to jump to the condition of the enclosing while loop.

continue in a for loop

Let's see what happens if continue appears in a for loop.

In a for loop, it jumps to the update.

for ( i = 0 ; i < num ; i++ )
{
   if ( i > num / 2 )
      continue ; // Jumps to update, i++
   System.out.println( "Here I am!" ) ;
}

continue with a label

As with break, you can use continue with a label. The label must appear just before one of the enclosing loops of the continue statement.

If the label appears before a while loop or a do while, then "continue with a label" jumps to the cond of the loop with the label.

If the label appears before a for loop, then it jumps to the update of that loop. As with "break with a label", "continue with a label" must have a label on an enclosing loop.

For now, avoid break and continue

Experience has shown that beginners use break and continue incorrectly. In particular, you see beginners writing:
while ( true ) // Intentional infinite loop
{
   // CODE
   break ;
   // MORE CODE
}
Writing conditions for a loop is tough. So, some beginners avoid writing conditions by using true for the condition. This causes an infinite loop. With break, infinite loops are no longer a problem. You use break to get out of the loop.

But it makes it more difficult to see when you exit a loop. As a programmer, you need to learn how to write loop conditions. By using break, there's a temptation not to learn it.

Later on, when you've mastered writing loop conditions and when you've seen break statements used by expert coders, then you can use break the way it's meant to be used.

In the meanwhile, avoid using break and continue, but understand how it works anyway.