The Java Tutorial: Control Flow

Now that you've gotten some experience with primitive data types and arrays, it's time to start looking at control flow statements in Java.

What is a control flow statement?

A control flow statement implements decision making in your code. An example of a control flow statement is an if-then block:

public class MyClass {
    public static void main(String args[]) {
        int i = 5;
        if(i < 10){
            System.out.println("i is less than 10");
        }
    }
}

Notice how we use control flow to print a message if i < 10. By executing code based on this condition, we are implementing decision making in Java.

Control flow statements can be described as either:

Decision making statements

  • if..then
  • if..then..else
  • switch

Looping statements

  • for
  • while
  • do..while

Branching statements

  • break
  • continue
  • return

In this tutorial, we'll explore these different types of control flow statements including examples of each, which to use, and why.

Decision Making Statements

if..then

The if..then block executes a block of code only if a given condition evaluates to true:

public class MyClass {
    public static void main(String args[]) {
        boolean isActive = true;
        if(isActive){
            System.out.println("Your account is active");
        }
    }
}

Notice how we set a boolean variable isActive to true. Since the expression within our if() clause evaluates to true, the code block inside {} gets executed, in this case printing "Your account is active".

The brackets are actually optional

In the example above, we can optionally omit the brackets {}. This generally isn't advised as it makes code less readable and becomes necessary with more complex logic like if..then..else

if..then..else

The if..then..else statement works just like if..then but provides a secondary or default option if a condition evaluates to false:

public class MyClass {
    public static void main(String args[]) {
        boolean isActive = false;
        if(isActive){
            System.out.println("Your account is active");
        } else{
            System.out.println("Account not found");
        }
    }
}

Notice how we set the isActive variable to false. This will cause our condition to evaluate to false, triggering the else block to execute, in this case printing "Account not found".

Multiple else statements

if..then..else is not limited to two outcomes:

public class MyClass {
    public static void main(String args[]) {
        int score = 14;
        if(score < 10){
            System.out.println("Your score is less than 10");
        } else if(score < 15){
            System.out.println("Your score is less than 15");
        } else if(score < 20) {
            System.out.println("Your score is less than 20");
        } else {
            System.out.println("Your score is off the charts!");
        }
        //prints "Your score is less than 15"
    }
}

With multiple if statements, the code will execute the first block that evaluates to true. Since the score variable is greater than 10, the first statement score < 10 is skipped. Since the second statement score < 15 evaluates to true, it's block is executed.

While the next condition score < 20 also evaluates to true, remember that the if..then block executes the first statement that evaluates to true. For these reasons, anything after the score < 15 block isn't executed.

switch

The switch statement tests a certain variable for equality against a number of different values or "cases":

public class MyClass {
    public static void main(String args[]) {
        int number = 2;
        switch(number){
            case 1: System.out.println("The number is 1");
                break;
            case 2:
                System.out.println("The number is 2");
                System.out.println("Thats an even number!");
                break;
            case 3: System.out.println("The number is 3");
                break;
            default: System.out.println("Please picker a number between 1 and 3");
                break;
        }
        //prints "The number is 2"
        //prints "Thats an even number!"
    }
}

Notice how our switch() statement accepts our number variable and tests it against different possible values. Since our number = 2, it satisfies the case 2 condition.

Notice how we can throw any code block within our case statement. We also provide a default case for any scenario where number does not match our cases (1,2,3).

Using break

Notice how we make use of break to exit the switch statement. Without using break, statements in switch blocks fall through:

public static void main(String args[]) {
    int number = 2;
    switch(number){
        case 1: System.out.println("The number is 1");
        case 2:
            System.out.println("The number is 2");
            System.out.println("Thats an even number!");
        case 3: System.out.println("The number is 3");
        default: System.out.println("Please picker a number between 1 and 3");
    }
    //prints "The number is 2"
    //prints "Thats an even number!"
}

If you run this code, it will print:

The number is 1
The number is 2
Thats an even number!
The number is 03
Please picker a number between 1 and 3

Without the break statement, the code doesn't understand to exit the switch statement and the rest of the cases get executed.

While the final break statement after default isn't required, it's considered best practice to use break here.

When to use switch over if..else

Both the if..else and switch statements provide decision making and control flow. Many times, these statements can be used to do the same thing.

While code readability is always a factor, remember that switch statements test expressions based on a single integer, enumerated value or string. Use switch when you want to test expected known values. Use if..else when you want to test against a range of values or conditions.

Looping Statements

while

The while statement will continually execute a block of code until a given condition is met:

public class MyClass {
    public static void main(String args[]) {
        int count = 1;
        while(count < 10){
            System.out.println(count);
            count++;
        }
    }
    //prints 1-9
}

Notice how the while statement executes the code block until the condition count < 10 evaluates to true.

If we didn't increment the count with count++, the while loop would run indefinitely and crash at runtime.

do..while

The do..while statement is similar however executes the code block once before the condition is evaluated for the first time:

public class MyClass {
    public static void main(String args[]) {
        int count = 11;
        do{
            System.out.println(count);
            count++;
        }
        while(count < 10);
    }
    //prints 11
}

Notice how the code block still executes once even though the initial value of count causes the expression count < 10 to evaluate to false.

When should I use do..while?

Use do..while when you need the code block to run at least once.

for

The for statement is used to iterate over a range of values:

public class MyClass {
    public static void main(String args[]) {
        for(int i=1; i < 6; i++){
            System.out.println(i);
        }
    }
}

If you run this code, it will print:

1
2
3
4
5

Notice how the for loop takes 3 statements. The first initializes a local variable int i=1, the second defines a termination expression i < 6 and the third defines an increment expression i++.

This loop continually executes the code block until the termination expression is met. Every time the block executes, it increments the variable i by 1.

Using for with arrays

Loops like for are popular for iterating over arrays and collections in Java. The for even has another implementation designed specifically for working with arrays:

public class MyClass {
    public static void main(String args[]) {
        char[] myArray = {'c', 'a', 't'};
        for(char item : myArray){
            System.out.println(item);
        }
    }
}

Notice how we first define a character array myArray. We then use the alternative syntax for working with arrays for(char item : myArray) to iterate over each item in the array. Note that we specify the data type char item so the loop knows what type to expect.

Branching Statements

break

The break statement can be used to terminate loops:

public class MyClass {
    public static void main(String args[]) {
        for(int i=1; i < 5; i++){
            System.out.println(i);
            if(i > 2){
                break;
            }
        }
    }
}

If you run this code, it prints:

1
2
3

Using break, we are able to manually exit the for loop before it reaches the termination case i < 5.

labeled break

The examples up to this point have used unlabeled breaks. Unlabeled breaks are good for terminating innermost loops and switch statements. Labeled breaks can be used to terminate outer statements:

public class MyClass {
    public static void main(String[] args) {
        int[] myArray = {1,2,3,4,5};

        nestedLoop:
            for(int i = 0; i < myArray.length; i++){
                for(int j = 0; i < myArray.length; i++){
                    System.out.println(myArray[j]);
                    break nestedLoop;
                }
            }
            //prints 1
    }
}

In this example, we use a labeled break statement break nestedLoop to terminate the outer for loop.

If we hadn't used a labeled break statement (aka just break), this example would continue to execute the outer loop, resulting in:

1
1
1
1
1

continue

The continue statement skips an iteration of a loop. For example:

public class MyClass {
    public static void main(String[] args) {
        int[] myArray = {1,2,3,4,5};
        for(int i=0; i < myArray.length; i++){
            if(i == 2)
                continue;
            System.out.println(i);
        }
    }
}

If you run this code, it will print:

0
1
3
4

Notice how we effectively skip an iteration by calling continue if a condition i == 2 is met.

return

The return statement is used to exit a method:

public class MyClass {
    public static void main(String[] args) {
        System.out.println("My age is " + getAge(50));
    }

    public static int getAge(int a) {
        return a;
    }
}

Notice how we've created a simple method getAge() that returns an integer provided as an argument. Remember that return can be used to return a value (in this case an integer a) or simply to exit a method (without a return value).

Conclusion

Control flow statements give you a way to implement decision making in your code. Decision making statements like if...else and switch can be used to execute code blocks based on given conditions. Looping statements like for and do..while can be used to iterate over arrays and collection. Branching statements like break and continue help control the flow of control flow statements and methods.

Your thoughts?