Previous | Next | Trail Map | Learning the Java Language | The Nuts and Bolts of the Java Language

Control Flow Statements

The countChars method uses a while statement to loop through all of the characters of the input source and count them:
import java.io.*;
public class Count {
    public static void countChars(Reader in) throws IOException
    {
        int count = 0;

        while (in.read() != -1)
            count++;
        System.out.println("Counted " + count + " chars.");
    }
    // ... main method omitted ...
}
Generally speaking, a while statement performs some action while a certain condition remains true. The general syntax of the while statement is:
while (expression)
    statement
That is, while expression is true, do statement. In countChars, while the read method returns a value that is not -1, the program increments count.


By Convention: The opening curly bracket { is at the end of the same line as the while statement, and the closing curly bracket } begins a new line aligned with the while, as shown.

statement can be one statement, as shown in countChars, or it can be a statement block. A statement block is a series of legal Java statements contained within curly brackets ('{' and '}'). For example, suppose that in addition to incrementing count within the while loop you also wanted to print the count each time a character was read. You could write this instead:

. . .
while (in.read() != -1) {
    count++;
    System.out.println("Read a character. Count = " + count);
}
. . .

A statement such as the while statement is a control flow statement, that is, it determines the order in which other statements are executed. Besides while, the Java language supports several other control flow statements, including:

Statement Keyword
decision making if-else, switch-case
loop for, while, do-while
exception try-catch-finally, throw
miscellaneous break, continue, label: , return

Note: Although goto is a reserved word, currently the Java language does not support the goto statement. Use Branching Statements instead.

The if-else Statement

Java's if-else statement provides your programs with the ability to selectively execute other statements based on some criteria. For example, suppose that your program printed debugging information based on the value of some boolean variable named DEBUG. If DEBUG were set to true, then your program would print debugging information such as the value of some variable like x. Otherwise, your program would proceed normally. A segment of code to implement this might look like this:
. . .
if (DEBUG)
    System.out.println("DEBUG: x = " + x);
. . .
This is the simplest version of the if statement: the statement governed by the if is executed if some condition is true. Generally, the simple form of if can be written like this:
if (expression)
    statement
So, what if you wanted to perform a different set of statements if the expression is false? Well, you can use the else statement for that. Consider another example. Suppose that your program needs to perform different actions depending on whether the user clicks on the OK button or the Cancel button in an alert window. Your program could do this using an if statement:
    . . .
    // response is either OK or CANCEL depending
    // on the button that the user pressed
    . . .
if (response == OK) {
    . . .
    // code to perform OK action
    . . .
} else {
    . . .
    // code to perform Cancel action
    . . .
}
This particular use of the else statement is the catch-all form. The else block is executed if the if part is false. There is another form of the else statement, else if which executes a statement based on another expression. For example, suppose that you wrote a program that assigned grades based on the value of a test score, an A for a score of 90% or above, a B for a score of 80% or above and so on. You could use an if statement with a series of companion else if statements, and an else to write this code:
int testscore;
char grade;

if (testscore >= 90) {
    grade = 'A';
} else if (testscore >= 80) {
    grade = 'B';
} else if (testscore >= 70) {
    grade = 'C';
} else if (testscore >= 60) {
    grade = 'D';
} else {
    grade = 'F';
}
An if statement can have any number of companion else if statements, but only one else. You may have noticed that some values of testscore could satisfy more than one of the expressions in the compound if statement. For instance, a score of 76 would evaluate to true for two of the expressions in the if statement: testscore >= 70 and testscore >= 60. However, as the runtime system processes a compound if statement such as this one, once a condition is satisfied (76 >= 70), the appropriate statements are executed (grade = 'C';), and control passes out of the if statement without evaluating the remaining conditions.

The switch Statement

Use the switch statement to conditionally perform statements based on some expression. For example, suppose that your program contained an integer named month whose value indicated the month in some date. Suppose also that you wanted to display the name of the month based on its integer equivalent. You could use Java's switch statement to perform this feat:
int month;
. . .
switch (month) {
case 1:  System.out.println("January"); break;
case 2:  System.out.println("February"); break;
case 3:  System.out.println("March"); break;
case 4:  System.out.println("April"); break;
case 5:  System.out.println("May"); break;
case 6:  System.out.println("June"); break;
case 7:  System.out.println("July"); break;
case 8:  System.out.println("August"); break;
case 9:  System.out.println("September"); break;
case 10: System.out.println("October"); break;
case 11: System.out.println("November"); break;
case 12: System.out.println("December"); break;
}
The switch statement evaluates its expression, in this case, the value of month, and executes the appropriate case statement. Of course, you could implement this as an if statement:
int month;
. . .
if (month == 1) {
    System.out.println("January");
} else if (month == 2) {
    System.out.println("February");
. . .
// you get the idea
. . .
Deciding whether to use an if statement or a switch statement is a judgment call. You can decide which to use based on readability and other factors. Each case statement must be unique and the value provided to each case statement must be of the same data type as the data type returned by the expression provided to the switch statement.

Another point of interest in the switch statement are the break statements after each case. The break statements cause control to break out of the switch and continue with the first statement following the switch. The break statements are necessary because case statements fall through. That is, without an explicit break control will flow sequentially through subsequent case statements. In the previous example, you don't want control to flow from one case to the next, so you have to put in break statements. However, there are certain scenarios when you do want control to proceed sequentially through case statements. Like in the following Java code that computes the number of days in a month according to the old rhyme that starts "Thirty days hath September...":

int month;
int numDays;
. . .
switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
    numDays = 31;
    break;
case 4:
case 6:
case 9:
case 11:
    numDays = 30;
    break;
case 2:
    if ( ((year % 4 == 0) && !(year % 100 == 0)) || (year % 400 == 0) )
        numDays = 29;
    else
        numDays = 28;
    break;
}
Finally, you can use the default statement at the end of the switch to handle all values that aren't explicitly handled by one of the case statements.
int month;
. . .
switch (month) {
case 1:  System.out.println("January"); break;
case 2:  System.out.println("February"); break;
case 3:  System.out.println("March"); break;
case 4:  System.out.println("April"); break;
case 5:  System.out.println("May"); break;
case 6:  System.out.println("June"); break;
case 7:  System.out.println("July"); break;
case 8:  System.out.println("August"); break;
case 9:  System.out.println("September"); break;
case 10: System.out.println("October"); break;
case 11: System.out.println("November"); break;
case 12: System.out.println("December"); break;
default: System.out.println("Hey, that's not a valid month!");
    break;
}

Loop Statements

You were introduced to Java's while statement above. Java has two other looping constructs that you can use in your programs: the for loop and the do-while loop.

Use the for loop when you know the constraints of the loop (its initialization instruction, termination criteria, and increment instruction). For instance, for loops are often used to iterate over the elements in an array, or the characters in a string.

// a is an array of some kind
. . .
int i;
int length = a.length;
for (i = 0; i < length; i++) {
    . . .
    // do something to the i th element of a
    . . .
}
You know when writing the program that you want to start at the beginning of the array, stop at the end, and hit every element. Thus the for statement is a good choice. The general form of the for statement can be expressed like this:
for (initialization; termination; increment)
    statements
initialization is a statement that initializes the loop--its executed once at the beginning of the loop. termination is an expression that determines when to terminate the loop. This expression is evaluated at the top of each iteration of the loop. When the expression evaluates to false, the for loop terminates. Finally, increment is an expression that gets invoked for each iteration through the loop. Any (or all) of these components can be empty statements (a single semi-colon by itself).

Java provides another loop, the do-while loop, which is similar to the while loop you met earlier except that the expression is evaluated at the bottom of the loop:

do {
    statements
} while (booleanExpression);
The do-while statement is a less commonly used loop construct in programming but does have its uses. For example, the do-while is convenient to use when the statements within the loop must be executed at least once. For example, when reading information from a file, you know that you will always have to read at least one character:
int c;
Reader in;
. . .
do {
    c = in.read();
    . . .
} while (c != -1);

Exception Handling Statements

When an error occurs within a Java method, the method can throw an exception to indicate to its caller that an error occurred and the type of error that occured. The calling method can use the try, catch, and finally statements to catch and handle the exception. See Handling Errors Using Exceptions(in the Learning the Java Language trail) for information about throwing and handling exceptions.

Branching Statements

You saw the break statement in action within the switch statement earlier. As noted there, break causes the flow of control to jump to the statement immediately following the current statement.

Another form of the break statement causes flow of control to break out of a labeled statement. You label a statement by placing a legal Java identifier (the label) followed by a colon (:) before the statement:

statementName: someJavaStatement
To break out of the statement labeled statementName use the following form of the break statement.
break statementName;
Labeled breaks are an alternative to the goto statement, which is not supported by the Java language.

Use the continue statement within loops to jump to another statement.


Note: The continue statement can only be called from within a loop.
The continue statement has two forms: unlabeled and labeled. If you use the unlabelled form, control transfers to the termination condition of the loop. The termination condition gets re-evaluated at this point and the loop either continues or not depending on the results of the test. In for and while loops, this means that control returns to the top of the loop. In do-while loops, this means that controls returns to the bottom of the loop.

The labeled form of the continue statement continues at the next iteration of the labeled loop. Consider this implementation of the String class's indexOf method which uses the labeled form of continue:

public int indexOf(String str, int fromIndex) {
    char[] v1 = value;
    char[] v2 = str.value;
    int max = offset + (count - str.count);
  test:
    for (int i = offset + ((fromIndex < 0) ? 0 : fromIndex); i <= max ; i++) {
        int n = str.count;
        int j = i;
        int k = str.offset;
        while (n-- != 0) {
            if (v1[j++] != v2[k++]) {
                continue test;
            }
        }    
        return i - offset;
    }
    return -1;
}

The last of Java's branching statements the return statement. You use return to exit from the current method and jump back to the statement within the calling method that follows the original method call. There are two forms of return: one that returns a value and one that doesn't. To return a value, simply put the value (or an expression that calculates the value after the return keyword:

return ++count;
The value returned by return must match the type of method's declared return value.

When a method is declared void use the form of return that doesn't return a value:

return;


Previous | Next | Trail Map | Learning the Java Language | The Nuts and Bolts of the Java Language