Md Mominul Islam | Software and Data Enginnering | SQL Server, .NET, Power BI, Azure Blog

while(!(succeed=try()));

LinkedIn Portfolio Banner

Latest

Home Top Ad

Responsive Ads Here

Saturday, August 30, 2025

Master Java Programming: Module 3 - Control Flow Tutorial for Beginners to Advanced

 


Table of Contents

  1. Conditional Statements

    • If Statement

    • If-Else Statement

    • Nested If Statements

    • Switch Statement

  2. Loops

    • For Loop

    • While Loop

    • Do-While Loop

  3. Break, Continue, and Return Statements

    • Break Statement

    • Continue Statement

    • Return Statement

  4. Java 21+ Enhanced Switch Expressions

  5. Boolean Logic and Short-Circuit Evaluation

  6. Conclusion

  7. Interactive Challenges


Conditional Statements

Control flow begins with decision-making, and conditional statements allow your Java program to choose different paths based on conditions. Think of them as the brain of your application, deciding what to do next—like a restaurant server choosing a dish based on a customer’s order.

If Statement

The if statement is the simplest way to make decisions in Java. It evaluates a Boolean expression and executes a block of code if the condition is true.

Real-Life Scenario: Imagine you’re building a weather app that checks if it’s raining to suggest an umbrella.

Basic Example:

public class WeatherApp {
    public static void main(String[] args) {
        boolean isRaining = true;

        if (isRaining) {
            System.out.println("Bring an umbrella!");
        }
    }
}

Output: Bring an umbrella!

Intermediate Example: Check temperature to decide activity.

public class ActivityPlanner {
    public static void main(String[] args) {
        int temperature = 25; // Celsius

        if (temperature > 20) {
            System.out.println("Go for a hike!");
        }
    }
}

Output: Go for a hike!

Advanced Example: Combine multiple conditions for a smart home system.

public class SmartHome {
    public static void main(String[] args) {
        int roomTemperature = 28;
        boolean isNight = true;

        if (roomTemperature > 25 && isNight) {
            System.out.println("Turn on the air conditioner and dim the lights.");
        }
    }
}

Output: Turn on the air conditioner and dim the lights.

Pros:

  • Simple and intuitive for basic decision-making.

  • Highly readable for small conditions.

Cons:

  • Can become unwieldy with multiple conditions.

  • Limited to a single branch of execution.

Best Practices:

  • Use clear, descriptive variable names (e.g., isRaining instead of x).

  • Keep conditions simple to avoid nested complexity.

  • Use curly braces {} even for single-line blocks to improve readability and prevent errors.

Alternatives:

  • Use switch for multiple discrete values.

  • Consider ternary operator (?:) for simple, single-expression conditions (e.g., String message = isRaining ? "Bring umbrella" : "Enjoy the sun";).

If-Else Statement

The if-else statement adds an alternative path when the if condition is false. It’s like a restaurant offering a vegetarian option if the customer doesn’t eat meat.

Real-Life Scenario: A ticket booking system that checks age for discounts.

Basic Example:

public class TicketBooking {
    public static void main(String[] args) {
        int age = 65;

        if (age >= 60) {
            System.out.println("Eligible for senior discount.");
        } else {
            System.out.println("Standard ticket price applies.");
        }
    }
}

Output: Eligible for senior discount.

Intermediate Example: Restaurant order system with dietary preferences.

public class RestaurantOrder {
    public static void main(String[] args) {
        boolean isVegetarian = true;

        if (isVegetarian) {
            System.out.println("Serve vegetarian pasta.");
        } else {
            System.out.println("Serve chicken pasta.");
        }
    }
}

Output: Serve vegetarian pasta.

Advanced Example: Multi-tier pricing based on customer loyalty.

public class LoyaltyProgram {
    public static void main(String[] args) {
        int purchaseAmount = 150;
        boolean isLoyalCustomer = true;

        if (isLoyalCustomer && purchaseAmount > 100) {
            System.out.println("Apply 20% discount.");
        } else if (purchaseAmount > 50) {
            System.out.println("Apply 10% discount.");
        } else {
            System.out.println("No discount applied.");
        }
    }
}

Output: Apply 20% discount.

Pros:

  • Handles multiple outcomes clearly.

  • Supports chaining with else if for complex decisions.

Cons:

  • Long if-else chains can reduce readability.

  • Overuse can lead to code duplication.

Best Practices:

  • Limit else if chains to 3–4 conditions; consider switch or polymorphism for more.

  • Extract complex logic into methods for clarity.

  • Use else only when necessary to avoid redundant branches.

Alternatives:

  • Use switch for discrete values.

  • Refactor complex if-else chains into a strategy pattern or lookup tables for maintainability.

Nested If Statements

Nested if statements involve placing if statements inside other if blocks, allowing for multi-level decision-making. Think of a medical diagnosis system checking symptoms step-by-step.

Real-Life Scenario: A hospital triage system prioritizing patients.

Basic Example:

public class TriageSystem {
    public static void main(String[] args) {
        boolean hasFever = true;
        boolean hasCough = true;

        if (hasFever) {
            if (hasCough) {
                System.out.println("Possible respiratory infection. Prioritize testing.");
            } else {
                System.out.println("Monitor fever. Schedule check-up.");
            }
        }
    }
}

Output: Possible respiratory infection. Prioritize testing.

Intermediate Example: Online shopping cart with shipping rules.

public class ShoppingCart {
    public static void main(String[] args) {
        double cartTotal = 75.0;
        boolean isInternational = true;

        if (cartTotal > 50) {
            if (isInternational) {
                System.out.println("Free international shipping.");
            } else {
                System.out.println("Free domestic shipping.");
            }
        } else {
            System.out.println("Shipping fee applies.");
        }
    }
}

Output: Free international shipping.

Advanced Example: Game character health system.

public class GameCharacter {
    public static void main(String[] args) {
        int health = 20;
        boolean hasShield = true;
        boolean isCritical = false;

        if (health < 30) {
            if (hasShield) {
                if (!isCritical) {
                    System.out.println("Low health, but shield protects. Continue battle.");
                } else {
                    System.out.println("Critical state! Retreat and heal.");
                }
            } else {
                System.out.println("Low health, no shield. Retreat immediately.");
            }
        } else {
            System.out.println("Health is stable. Proceed with mission.");
        }
    }
}

Output: Low health, but shield protects. Continue battle.

Pros:

  • Allows fine-grained control over complex conditions.

  • Useful for hierarchical decision-making.

Cons:

  • Deep nesting reduces readability (“arrow code”).

  • Harder to debug and maintain.

Best Practices:

  • Limit nesting to 2–3 levels; refactor deeper nests into methods or separate classes.

  • Use guard clauses to exit early and reduce nesting.

  • Comment complex nested logic for clarity.

Alternatives:

  • Use && or || to combine conditions in a single if.

  • Refactor using state machines or decision tables for complex logic.

Switch Statement

The switch statement selects a block of code to execute based on a variable’s value. It’s ideal for discrete, predefined options, like a menu system in a game.

Real-Life Scenario: A vending machine selecting products.

Basic Example:

public class VendingMachine {
    public static void main(String[] args) {
        int selection = 2;

        switch (selection) {
            case 1:
                System.out.println("Dispensing soda.");
                break;
            case 2:
                System.out.println("Dispensing chips.");
                break;
            case 3:
                System.out.println("Dispensing candy.");
                break;
            default:
                System.out.println("Invalid selection.");
        }
    }
}

Output: Dispensing chips.

Intermediate Example: Traffic light controller.

public class TrafficLight {
    public static void main(String[] args) {
        String light = "GREEN";

        switch (light.toUpperCase()) {
            case "RED":
                System.out.println("Stop!");
                break;
            case "YELLOW":
                System.out.println("Slow down.");
                break;
            case "GREEN":
                System.out.println("Go!");
                break;
            default:
                System.out.println("Invalid signal.");
        }
    }
}

Output: Go!

Advanced Example: Role-based access control.

public class AccessControl {
    public static void main(String[] args) {
        String userRole = "ADMIN";
        int accessLevel = 3;

        switch (userRole) {
            case "ADMIN":
                if (accessLevel >= 3) {
                    System.out.println("Full system access granted.");
                } else {
                    System.out.println("Limited admin access.");
                }
                break;
            case "USER":
                System.out.println("Standard user access.");
                break;
            case "GUEST":
                System.out.println("Read-only access.");
                break;
            default:
                System.out.println("Access denied.");
        }
    }
}

Output: Full system access granted.

Pros:

  • Cleaner than long if-else chains for discrete values.

  • Efficient for multiple fixed options.

Cons:

  • Limited to equality checks (no range or complex conditions).

  • Requires break to avoid fall-through (unless intentional).

Best Practices:

  • Always include a default case to handle unexpected inputs.

  • Use break unless fall-through is intentional and documented.

  • Prefer switch for enums or fixed integer/string values.

Alternatives:

  • Use if-else for complex conditions or ranges.

  • Consider Map or enums for dynamic or extensible options.


Loops

Loops allow your program to repeat actions, like processing a list of orders or updating a game’s state. Java provides for, while, and do-while loops to handle repetition.

For Loop

The for loop is ideal for iterating a known number of times, like processing items in a shopping cart.

Real-Life Scenario: Calculating total cost in an e-commerce cart.

Basic Example:

public class ShoppingCartTotal {
    public static void main(String[] args) {
        double[] prices = {10.99, 5.49, 3.99};

        double total = 0;
        for (int i = 0; i < prices.length; i++) {
            total += prices[i];
        }
        System.out.println("Total: $" + total);
    }
}

Output: Total: $20.47

Intermediate Example: Generating a multiplication table.

public class MultiplicationTable {
    public static void main(String[] args) {
        int number = 5;

        for (int i = 1; i <= 10; i++) {
            System.out.println(number + " x " + i + " = " + (number * i));
        }
    }
}

Output:

5 x 1 = 5
5 x 2 = 10
...
5 x 10 = 50

Advanced Example: Processing a 2D grid (e.g., game map).

public class GameMap {
    public static void main(String[] args) {
        char[][] map = {
            {'#', '.', '.'},
            {'.', '#', '.'},
            {'.', '.', '#'}
        };

        for (int row = 0; row < map.length; row++) {
            for (int col = 0; col < map[row].length; col++) {
                if (map[row][col] == '#') {
                    System.out.println("Wall at position (" + row + ", " + col + ")");
                }
            }
        }
    }
}

Output:

Wall at position (0, 0)
Wall at position (1, 1)
Wall at position (2, 2)

Pros:

  • Compact syntax for known iteration counts.

  • Ideal for array and collection iteration.

Cons:

  • Less flexible for dynamic or condition-based iteration.

  • Index management can lead to off-by-one errors.

Best Practices:

  • Use enhanced for loop (for-each) for simple collection iteration.

  • Validate array/collection bounds to avoid ArrayIndexOutOfBoundsException.

  • Avoid modifying loop variables inside the loop.

Alternatives:

  • Use while for condition-driven loops.

  • Use forEach or streams for collections in modern Java.

While Loop

The while loop repeats as long as a condition is true, perfect for scenarios with uncertain iteration counts, like reading user input.

Real-Life Scenario: A game loop waiting for player input.

Basic Example:

import java.util.Scanner;

public class GuessNumber {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int secretNumber = 42;
        int guess;

        System.out.print("Guess the number: ");
        guess = scanner.nextInt();

        while (guess != secretNumber) {
            System.out.print("Wrong! Try again: ");
            guess = scanner.nextInt();
        }
        System.out.println("Correct! The number is " + secretNumber);
    }
}

Output (example interaction):

Guess the number: 50
Wrong! Try again: 42
Correct! The number is 42

Intermediate Example: ATM withdrawal limit.

public class ATM {
    public static void main(String[] args) {
        double balance = 1000.0;
        double withdrawal = 300.0;

        while (balance >= withdrawal) {
            balance -= withdrawal;
            System.out.println("Withdrawn $" + withdrawal + ". New balance: $" + balance);
        }
        System.out.println("Insufficient funds.");
    }
}

Output:

Withdrawn $300.0. New balance: $700.0
Withdrawn $300.0. New balance: $400.0
Withdrawn $300.0. New balance: $100.0
Insufficient funds.

Advanced Example: Simulating a server queue.

import java.util.LinkedList;
import java.util.Queue;

public class ServerQueue {
    public static void main(String[] args) {
        Queue<String> requests = new LinkedList<>();
        requests.add("User1");
        requests.add("User2");
        requests.add("User3");

        while (!requests.isEmpty()) {
            String user = requests.poll();
            System.out.println("Processing request from " + user);
        }
        System.out.println("All requests processed.");
    }
}

Output:

Processing request from User1
Processing request from User2
Processing request from User3
All requests processed.

Pros:

  • Flexible for dynamic conditions.

  • Suitable for indefinite loops.

Cons:

  • Risk of infinite loops if condition is not updated.

  • Less structured than for for known iterations.

Best Practices:

  • Ensure the loop condition will eventually be false.

  • Use clear exit conditions to avoid infinite loops.

  • Initialize variables before the loop to prevent null or undefined states.

Alternatives:

  • Use for for known iteration counts.

  • Use do-while if at least one iteration is guaranteed.

Do-While Loop

The do-while loop executes at least once before checking the condition, ideal for scenarios requiring initial action, like a menu system.

Real-Life Scenario: A restaurant order system prompting for input.

Basic Example:

import java.util.Scanner;

public class MenuSystem {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int choice;

        do {
            System.out.println("1. Order Food\n2. Exit");
            System.out.print("Enter choice: ");
            choice = scanner.nextInt();
        } while (choice != 2);
        System.out.println("Thank you for visiting!");
    }
}

Output (example interaction):

1. Order Food
2. Exit
Enter choice: 1
1. Order Food
2. Exit
Enter choice: 2
Thank you for visiting!

Intermediate Example: Retry mechanism for a login system.

public class LoginSystem {
    public static void main(String[] args) {
        String password = "secure123";
        String input;
        Scanner scanner = new Scanner(System.in);
        int attempts = 3;

        do {
            System.out.print("Enter password (" + attempts + " attempts left): ");
            input = scanner.nextLine();
            attempts--;
        } while (!input.equals(password) && attempts > 0);

        if (input.equals(password)) {
            System.out.println("Login successful!");
        } else {
            System.out.println("Account locked.");
        }
    }
}

Output (successful login):

Enter password (3 attempts left): secure123
Login successful!

Advanced Example: Processing sensor data until valid.

public class SensorReader {
    public static void main(String[] args) {
        double temperature;
        int readings = 0;

        do {
            temperature = Math.random() * 50; // Simulate sensor reading
            System.out.println("Reading #" + (++readings) + ": " + temperature + "°C");
        } while (temperature < 0 || temperature > 40); // Valid range: 0–40°C

        System.out.println("Valid temperature recorded: " + temperature + "°C");
    }
}

Output (varies due to randomness):

Reading #1: 45.2°C
Reading #2: 25.7°C
Valid temperature recorded: 25.7°C

Pros:

  • Guarantees at least one execution.

  • Useful for user input or retry mechanisms.

Cons:

  • Less common than for or while.

  • Condition must be carefully managed to avoid infinite loops.

Best Practices:

  • Use when at least one iteration is required.

  • Clearly document the exit condition.

  • Avoid complex logic in the do block to maintain readability.

Alternatives:

  • Use while if the loop might not need to run.

  • Use for for fixed iterations.


Break, Continue, and Return Statements

These statements modify control flow within loops and methods, allowing you to exit, skip, or return values early.

Break Statement

The break statement exits a loop or switch immediately, useful for stopping when a condition is met.

Real-Life Scenario: Searching for a product in inventory.

Basic Example:

public class InventorySearch {
    public static void main(String[] args) {
        String[] inventory = {"Apple", "Banana", "Orange", "Grape"};
        String searchItem = "Orange";

        for (String item : inventory) {
            if (item.equals(searchItem)) {
                System.out.println(searchItem + " found!");
                break;
            }
        }
    }
}

Output: Orange found!

Intermediate Example: Stopping a game loop on game over.

public class GameLoop {
    public static void main(String[] args) {
        int playerHealth = 100;
        int damage = 30;

        while (playerHealth > 0) {
            playerHealth -= damage;
            System.out.println("Player health: " + playerHealth);
            if (playerHealth <= 0) {
                System.out.println("Game Over!");
                break;
            }
        }
    }
}

Output:

Player health: 70
Player health: 40
Player health: 10
Player health: -20
Game Over!

Advanced Example: Labeled break for nested loops.

public class MatrixSearch {
    public static void main(String[] args) {
        int[][] matrix = {
            {1, 2, 3},
            {4, 5, 6},
            {7, 8, 9}
        };
        int target = 5;

        outerLoop: for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[i].length; j++) {
                if (matrix[i][j] == target) {
                    System.out.println("Found " + target + " at (" + i + ", " + j + ")");
                    break outerLoop;
                }
            }
        }
    }
}

Output: Found 5 at (1, 1)

Pros:

  • Efficiently exits loops when a condition is met.

  • Labeled break handles nested loops cleanly.

Cons:

  • Overuse can make code harder to follow.

  • Labeled break can reduce readability if not documented.

Best Practices:

  • Use sparingly to maintain code clarity.

  • Prefer early loop termination conditions over break when possible.

  • Use labeled break only for complex nested loops with clear comments.

Alternatives:

  • Refactor loop logic to use conditions instead of break.

  • Use return to exit both loop and method.

Continue Statement

The continue statement skips the current iteration and proceeds to the next, useful for filtering data.

Real-Life Scenario: Processing valid transactions only.

Basic Example:

public class TransactionProcessor {
    public static void main(String[] args) {
        double[] transactions = {100.0, -50.0, 200.0, -30.0};

        for (double amount : transactions) {
            if (amount < 0) {
                continue;
            }
            System.out.println("Processing transaction: $" + amount);
        }
    }
}

Output:

Processing transaction: $100.0
Processing transaction: $200.0

Intermediate Example: Skipping invalid user inputs.

import java.util.Scanner;

public class InputValidator {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int validInputs = 0;

        while (validInputs < 3) {
            System.out.print("Enter a positive number: ");
            int number = scanner.nextInt();
            if (number <= 0) {
                System.out.println("Invalid input. Try again.");
                continue;
            }
            validInputs++;
            System.out.println("Valid input #" + validInputs + ": " + number);
        }
    }
}

Output (example interaction):

Enter a positive number: -5
Invalid input. Try again.
Enter a positive number: 10
Valid input #1: 10
Enter a positive number: 20
Valid input #2: 20
Enter a positive number: 0
Invalid input. Try again.
Enter a positive number: 30
Valid input #3: 30

Advanced Example: Labeled continue in nested loops.

public class BatchProcessor {
    public static void main(String[] args) {
        int[][] batches = {
            {1, -2, 3},
            {-4, 5, 6},
            {7, -8, 9}
        };

        outerLoop: for (int[] batch : batches) {
            for (int value : batch) {
                if (value < 0) {
                    System.out.println("Skipping negative value: " + value);
                    continue outerLoop;
                }
                System.out.println("Processing value: " + value);
            }
        }
    }
}

Output:

Processing value: 1
Skipping negative value: -2
Skipping negative value: -4
Processing value: 7
Skipping negative value: -8

Pros:

  • Simplifies skipping invalid or unwanted iterations.

  • Labeled continue handles complex nested loop skips.

Cons:

  • Can make code harder to follow if overused.

  • Labeled continue requires careful documentation.

Best Practices:

  • Use continue to skip invalid data clearly.

  • Avoid deep nesting with continue; refactor if possible.

  • Document labeled continue usage.

Alternatives:

  • Use conditional blocks to filter data before looping.

  • Refactor into methods to handle complex skipping logic.

Return Statement

The return statement exits a method, optionally returning a value, and is often used to terminate control flow early.

Real-Life Scenario: Validating user credentials in a login system.

Basic Example:

public class CredentialChecker {
    public static boolean isValidUser(String username) {
        if (username == null || username.isEmpty()) {
            return false;
        }
        return true;
    }

    public static void main(String[] args) {
        String user = "Alice";
        if (isValidUser(user)) {
            System.out.println("User is valid.");
        } else {
            System.out.println("Invalid user.");
        }
    }
}

Output: User is valid.

Intermediate Example: Early return in a calculation.

public class TaxCalculator {
    public static double calculateTax(double income, boolean isResident) {
        if (income <= 0) {
            return 0.0;
        }
        if (!isResident) {
            return income * 0.3; // 30% for non-residents
        }
        return income * 0.2; // 20% for residents
    }

    public static void main(String[] args) {
        double tax = calculateTax(50000, true);
        System.out.println("Tax: $" + tax);
    }
}

Output: Tax: $10000.0

Advanced Example: Early return in a search method.

public class ProductSearch {
    public static String findProduct(String[] products, String target) {
        for (String product : products) {
            if (product.equalsIgnoreCase(target)) {
                return "Found: " + product;
            }
        }
        return "Product not found.";
    }

    public static void main(String[] args) {
        String[] products = {"Laptop", "Phone", "Tablet"};
        String result = findProduct(products, "phone");
        System.out.println(result);
    }
}

Output: Found: Phone

Pros:

  • Simplifies code by exiting early.

  • Improves readability by reducing nesting.

Cons:

  • Overuse can make method flow hard to follow.

  • Multiple return statements can complicate debugging.

Best Practices:

  • Use early return to handle invalid cases (guard clauses).

  • Ensure all code paths return a value for non-void methods.

  • Document complex return logic.

Alternatives:

  • Use break or continue for loop-specific exits.

  • Refactor complex methods into smaller ones to reduce return usage.


Java 21+ Enhanced Switch Expressions

Introduced in Java 14 and refined in Java 21, enhanced switch expressions modernize the switch statement with arrow syntax (->), expression support, and yield. They’re perfect for concise, readable code in scenarios like menu systems or state machines.

Real-Life Scenario: A customer support chatbot routing queries.

Basic Example:

public class Chatbot {
    public static void main(String[] args) {
        String queryType = "BILLING";

        String response = switch (queryType) {
            case "BILLING" -> "Redirecting to billing support.";
            case "TECHNICAL" -> "Redirecting to technical support.";
            case "GENERAL" -> "Redirecting to general support.";
            default -> "Invalid query type.";
        };
        System.out.println(response);
    }
}

Output: Redirecting to billing support.

Intermediate Example: Grade calculator with yield.

public class GradeCalculator {
    public static void main(String[] args) {
        int score = 85;

        String grade = switch (score / 10) {
            case 10, 9 -> "A";
            case 8 -> "B";
            case 7 -> "C";
            case 6 -> "D";
            default -> {
                if (score < 0 || score > 100) {
                    yield "Invalid score";
                } else {
                    yield "F";
                }
            }
        };
        System.out.println("Grade: " + grade);
    }
}

Output: Grade: B

Advanced Example: State machine for an order system.

public class OrderSystem {
    public static void main(String[] args) {
        String orderStatus = "SHIPPED";
        int days = 2;

        String deliveryEstimate = switch (orderStatus) {
            case "PROCESSING" -> "Order will ship in 3–5 days.";
            case "SHIPPED" -> switch (days) {
                case 1 -> "Arrives tomorrow.";
                case 2, 3 -> "Arrives in " + days + " days.";
                default -> "Check tracking for details.";
            };
            case "DELIVERED" -> "Order delivered.";
            default -> "Unknown status.";
        };
        System.out.println(deliveryEstimate);
    }
}

Output: Arrives in 2 days.

Pros:

  • Concise syntax with arrow (->) and no break.

  • Supports expressions, reducing boilerplate.

  • yield allows complex logic in blocks.

Cons:

  • Requires Java 14+ (standard in Java 21).

  • Less familiar to developers used to traditional switch.

Best Practices:

  • Use arrow syntax for simple cases.

  • Use yield for complex logic in blocks.

  • Ensure all cases are covered or include a default.

Alternatives:

  • Use traditional switch for older Java versions.

  • Use if-else for non-discrete conditions.

  • Consider enums or Map for extensible mappings.


Boolean Logic and Short-Circuit Evaluation

Boolean logic (&&, ||, !) and short-circuit evaluation optimize condition checks by evaluating only what’s necessary. They’re crucial for efficient and safe code, like validating user inputs.

Real-Life Scenario: Form validation in a web application.

Basic Example:

public class FormValidator {
    public static void main(String[] args) {
        String username = "Alice";
        String password = "secure123";

        if (username != null && !username.isEmpty()) {
            System.out.println("Username is valid.");
        }
    }
}

Output: Username is valid.

Intermediate Example: Short-circuit to prevent errors.

public class SafeAccess {
    public static void main(String[] args) {
        String[] data = {"Item1", null, "Item3"};

        for (String item : data) {
            if (item != null && item.length() > 4) {
                System.out.println("Valid item: " + item);
            }
        }
    }
}

Output: (No output, as no item has length > 4)

Advanced Example: Complex validation with short-circuit.

public class PaymentValidator {
    public static boolean isValidPayment(String cardNumber, double amount, boolean isOnline) {
        return cardNumber != null &&
               cardNumber.length() == 16 &&
               amount > 0 &&
               (isOnline || verifyCard(cardNumber));
    }

    private static boolean verifyCard(String cardNumber) {
        System.out.println("Verifying card: " + cardNumber);
        return true; // Simulated card verification
    }

    public static void main(String[] args) {
        boolean isValid = isValidPayment("1234567890123456", 50.0, true);
        System.out.println("Payment valid: " + isValid);
    }
}

Output:

Payment valid: true

(Note: verifyCard not called due to short-circuit with isOnline being true.)

Pros:

  • Short-circuit evaluation prevents unnecessary computations.

  • Improves performance and safety (e.g., null checks).

Cons:

  • Can obscure logic if conditions are complex.

  • Misuse can lead to unexpected behavior.

Best Practices:

  • Place null or error-prone checks first in && chains.

  • Use parentheses to clarify complex Boolean expressions.

  • Avoid side effects in conditions to prevent confusion with short-circuiting.

Alternatives:

  • Use explicit if blocks for clarity in complex cases.

  • Refactor complex logic into separate methods.


Conclusion

Mastering control flow in Java is like learning to navigate a city—you need to know when to turn (if, switch), loop back (for, while, do-while), or exit early (break, continue, return). With Java 21+ enhanced switch expressions and Boolean logic, you can write concise, efficient, and modern code. This module covered real-life scenarios, from restaurant systems to game loops, with examples ranging from basic to advanced. By following best practices and understanding pros, cons, and alternatives, you’re equipped to handle any control flow challenge.

No comments:

Post a Comment

Thanks for your valuable comment...........
Md. Mominul Islam