6. Mastering Control Flow in Java: A Guide to Dynamic Programming

In Java, statements normally execute from top to bottom. Real-world scenarios, however, often require us to:

  • Make decisions (e.g., deciding a user’s access level).
  • Repeat tasks (e.g., showing a menu until a user chooses to exit).
  • Handle unexpected errors without crashing.

Java’s control flow statements (e.g., if, switch, loops, branching statements, and exceptions) allow you to handle all these scenarios and more.


Comparison and Logical Operators

All control flow statements rely on boolean conditions—expressions that evaluate to either true or false.

Comparison Operators

Operator Description Example Result
== Checks equality 6 == 6 true
!= Checks if values are different 8 != 3 true
> Checks if left side is greater 4 > 6 false
< Checks if left side is smaller 2 < 9 true
>= Greater than or equal 5 >= 5 true
<= Less than or equal 12 <= 8 false

Examples:

  • 10 == 10true
  • 10 != 10false
  • 3 >= 5false

Logical Operators

Use logical operators to combine multiple comparison conditions:

  1. AND (&&): Returns true only if all conditions are true.

    • (7 > 2) && (3 == 3)true && truetrue
    • (7 > 2) && (3 > 5)true && falsefalse
  2. OR (||): Returns true if at least one condition is true.

    • (1 == 1) || (2 > 10)true || falsetrue
    • (5 != 5) || (2 > 10)false || falsefalse

Decision-Making Statements

Decision-making statements let your program choose among different paths based on certain conditions.

The if Statement

The if statement evaluates a condition and executes specific code if that condition is true.

if (condition) {
    // Code runs if 'condition' is true
} else if (anotherCondition) {
    // Runs if 'condition' was false, but 'anotherCondition' is true
} else {
    // Runs only if all above conditions are false
}

Example: Checking an integer score and assigning a grade band.

Scanner input = new Scanner(System.in);
System.out.print("Enter your score (0 - 100): ");

int score = input.nextInt();

if (score < 0 || score > 100) {
    System.out.println("Error: Score out of range!");
} else if (score >= 90) {
    System.out.println("Grade: A");
} else if (score >= 80) {
    System.out.println("Grade: B");
} else if (score >= 70) {
    System.out.println("Grade: C");
} else if (score >= 60) {
    System.out.println("Grade: D");
} else {
    System.out.println("Grade: F");
}

  • First, it checks if the score is invalid (below 0 or above 100).
  • Then it checks descending thresholds: 90, 80, 70, 60.
  • If none match, a final else assigns the lowest grade.

Output:

Enter your score (0 – 100): 90
Grade: A

The Ternary Operator

For quick conditions that set a single value, the ternary operator is handy:

Scanner input = new Scanner(System.in);
System.out.print("Enter your score: ");
int score = input.nextInt();
String message = (score >= 60) ? "Pass" : "Fail";
System.out.println(message);
  • If score >= 60 is true, message becomes "Pass".
  • Otherwise, message becomes "Fail".

Output:

Enter your score: 75
Pass


The switch Statement

When you have multiple specific cases to compare, a switch statement can be cleaner than a chain of else ifs.

Scanner input = new Scanner(System.in);
System.out.print("Enter a language code (e.g., 'ES', 'FR'): ");
String languageCode = input.nextLine().toUpperCase();
switch (languageCode) {
  case "ES":
    System.out.println("Hola, Mundo!");
  break;
  case "FR":
    System.out.println("Bonjour, le monde!");
  break;
  case "DE":
    System.out.println("Hallo, Welt!");
  break;
  default:
    System.out.println("Hello, World!");
  break;
}
  • Each case checks the exact value of languageCode.
  • If no case matches, default runs.

Output:

Enter a language code (e.g., ‘ES’, ‘FR’): ES
Hola, Mundo!

Simplified Switch (Java 12+)

Java 12 introduced arrow case labels:

Scanner input = new Scanner(System.in);
System.out.print("Enter language code (ES, FR, DE): ");
String languageCode = input.next().toUpperCase();
switch (languageCode) {
  case "ES" -> System.out.println("Hola, Mundo!");
  case "FR" -> System.out.println("Bonjour, le monde!");
   case "DE" -> System.out.println("Hallo, Welt!");
   default -> System.out.println("Hello, World!");
}

No break needed, but be mindful that older Java versions don’t support this syntax.

Output:

Enter language code (ES, FR, DE): FR
Bonjour, le monde!

Switch Expressions

You can also assign a value to a variable from a switch:

int day = 6; // You can change this value to test different days
String dayName = switch (day) {
  case 1 -> "Monday";
  case 2 -> "Tuesday";
  case 3 -> "Wednesday";
  case 4 -> "Thursday";
  case 5 -> "Friday";
  case 6, 7 -> "Weekend";
  default -> "Unknown";
};
System.out.println("Today is: " + dayName);

Output:

Today is: Weekend

  • If day is 6 or 7, the expression evaluates to "Weekend".
  • If day is outside 1–7, it defaults to "Unknown".

Looping Statements

Loops let you repeat a block of code until a certain condition is met or a certain count is reached.

The for Loop

A for loop is perfect when you know how many times you want to repeat something.

for (int i = 1; i <= 4; i++) {
  System.out.println("Iteration #" + i);
}

Explanation:

  1. Initialization: int i = 1 runs once.
  2. Condition: i <= 4 is checked; if true, enter the loop block.
  3. Increment: i++ runs after each loop iteration.

Output:

Iteration #1
Iteration #2
Iteration #3
Iteration #4

Looping through an array:

String[] colors = {"Red", "Green", "Blue"};
for (int idx = 0; idx < colors.length; idx++) {
  System.out.println(colors[idx]);
}
Output:
Red
Green
Blue

Enhanced For Loop

When you only need to read each element, an enhanced for loop is simpler:

int[] numbers = {3, 6, 9, 12};
for (int num : numbers) {
  System.out.println(num);
}

Each loop iteration assigns an element of the array to num.

Output:

3
6
9
12

The while Loop

Use while when the number of iterations isn’t known beforehand, but you keep looping as long as the condition is true:

int balance = 15;
while (balance > 0) {
  System.out.println("Current balance: $" + balance);
balance -= 3; // reduce by 3 each iteration
}

The loop will stop when balance is no longer greater than 0.

Output:

Current balance: $15
Current balance: $12
Current balance: $9
Current balance: $6
Current balance: $3

The do-while Loop

A do-while loop runs at least once before checking its condition.

Scanner input = new Scanner(System.in);
int attempts = 0;
int guess;
do {
  System.out.print("Guess a number (1-5): ");
  guess = input.nextInt();
  attempts++;
} while (guess != 3);
System.out.println("Correct! You guessed it in " + attempts + " tries.");

The user is prompted at least once regardless of whether the condition is true.

Output:

Guess a number (1-5): 2
Guess a number (1-5): 3
Correct! You guessed it in 2 tries.


Branching Statements

break

break exits the nearest loop or switch immediately.

for (int j = 1; j <= 10; j++) {
  if (j == 5) {
    break; // stops loop at j=5
  }
System.out.println("j = " + j);
}
Output:
j = 1
j = 2
j = 3
j = 4

continue

continue skips the rest of the current loop iteration and moves on to the next iteration:

for (int j = 1; j <= 5; j++) {
  if (j == 3) {
    continue; // skip printing when j=3
  }
  System.out.println("Value of j: " + j);
}
Output:
Value of j: 1
Value of j: 2
Value of j: 4
Value of j: 5

Here, 3 is never printed.


Exception Handling

Even well-written code can face unexpected errors. Exceptions allow your program to detect and handle these errors rather than abruptly crash.

Try-Catch-Finally

Scanner input = new Scanner(System.in);
try
{
  System.out.print("Enter dividend: ");
  int dividend = input.nextInt();
  System.out.print("Enter divisor: ");
  int divisor = input.nextInt();
  System.out.println("Result: " + (dividend / divisor));
} catch (ArithmeticException e) {
  System.out.println("Cannot divide by zero!");
} catch (InputMismatchException e) {
  System.out.println("Invalid input. Please enter an integer.");
} finally {
  System.out.println("End of try-catch example.");
}
  • try: Code that might fail (e.g., division by zero).
  • catch: Handles specific exceptions.
  • finally: Always executes, whether an exception was thrown or not.

Output:

Case 1: Valid Input
Enter dividend: 10
Enter divisor: 2
Result: 5
End of trycatch example.

Case 2: Division by Zero
Enter dividend: 10
Enter divisor: 0
Cannot divide by zero!
End of trycatch example.

Case 3: Invalid Input
Enter dividend: abc
Invalid input. Please enter an integer.
End of trycatch example.

Catching More Specific Errors

Java has many specialized exception classes:

  • ArithmeticException: For arithmetic errors (divide by zero, overflow).
  • InputMismatchException: When input type doesn’t match expectations.
  • ArrayIndexOutOfBoundsException: When accessing invalid array indices.
  • And so on.

You can chain catch blocks for different errors:

Scanner input = new Scanner(System.in);
try
{
  System.out.print("Pick an array index (0-4): ");
  int idx = input.nextInt();
if (idx < 0) {
    throw new ArrayIndexOutOfBoundsException("Negative index!");
  }
  int[] myArray = {100, 200, 300, 400, 500};
  System.out.println("Value at index " + idx + " is " + myArray[idx]);
} catch (ArrayIndexOutOfBoundsException e) {
  System.out.println("Error: " + e.getMessage());
} catch (InputMismatchException e) {
  System.out.println("Error: Enter an integer, please.");
} catch (Exception e) {
  System.out.println("General error: " + e.getMessage());
}

Here, we even throw an exception (throw new ArrayIndexOutOfBoundsException) if the user tries a negative index.

Output:

Case 1: Valid Input
Pick an array index (0-4): 2
Value at index 2 is 300

Case 2: Out of Bounds
Pick an array index (0-4): 5
Error: Index 5 out of bounds for length 5

Case 3: Negative Index
Pick an array index (04): –1
Error: Negative index!

Case 4: Invalid Input
Pick an array index (04): abc
Error: Enter an integer, please.


Putting It All Together

By combining these control flow tools, you can handle almost any logic:

  • Comparisons and logical operators form the backbone of conditions.
  • if / switch statements let you handle multiple scenarios elegantly.
  • Loops (for, while, do-while, enhanced for) let you automate repetitive tasks.
  • Branching (break, continue) refines how loops operate.
  • Exception handling (try, catch, finally, custom throw) makes your code resilient against runtime errors.

Example: A small menu-driven program with error handling:

Scanner input = new Scanner(System.in);
boolean running = true;
while (running) {
  System.out.println("\n--- Simple Calculator ---");
  System.out.println("1. Add");
  System.out.println("2. Subtract");
  System.out.println("3. Exit");
  System.out.print("Choose an option: ");
try {
    int choice = input.nextInt();
    switch (choice) {
      case 1 -> {
        System.out.print("Enter two integers to add: ");
        int a = input.nextInt();
        int b = input.nextInt();
        System.out.println("Sum = " + (a + b));
      }
      case 2 -> {
        System.out.print("Enter two integers to subtract: ");
        int x = input.nextInt();
        int y = input.nextInt();
        System.out.println("Difference = " + (x - y));
      }
      case 3 -> {
        System.out.println("Exiting...");
        running = false;
      }
      default -> System.out.println("Invalid option!");
      }
  } catch (InputMismatchException e) {
    System.out.println("Error: Please enter a valid integer.");
    input.nextLine(); // clear invalid input
  }
}
System.out.println("Program terminated.");
  • Uses a while loop to continuously display a menu until the user chooses to exit.
  • Switch statement handles different options.
  • Try-catch guards against invalid integer inputs.

Output:

Case 1: Valid Addition
1. Add
2. Subtract
3. Exit
Choose an option: 1
Enter two integers to add: 10 20
Sum = 30

Case 2: Valid Subtraction
1. Add
2. Subtract
3. Exit Choose an option: 2
Enter two integers to subtract: 50 15
Difference = 35

Case 3: Invalid Option
1. Add
2. Subtract
3. Exit Choose an option: 5
Invalid option!

Case 4: Non-Integer Input
1. Add
2. Subtract
3. Exit Choose an option: abc
Error: Please enter a valid integer.

Case 5: Exit
1. Add
2. Subtract
3. Exit Choose an option: 3
Exiting…
Program terminated.


Conclusion

Control flow in Java is all about guiding the order in which statements execute, ensuring that your program behaves correctly in a variety of scenarios:

  1. Make decisions with if/else and switch.
  2. Repeat tasks with for, while, and do-while loops.
  3. Branch your loops with break and continue.
  4. Handle errors gracefully using try-catch-finally blocks and specific exception classes.

By mastering these constructs, you’ll be able to write flexible, error-tolerant programs that handle both normal and unexpected conditions in a clear, structured way.

Share this article
Shareable URL
Prev Post

5. Interactive Java Programs: Gathering and Displaying User Input

Next Post

“Doc, JavaDoc and Markdown” with Jonathan Gibbons

Leave a Reply

Your email address will not be published. Required fields are marked *

Read next

1. Introduction to Java

Welcome to Java programming!This series of posts is designed to be a refresher for experienced developers and a…