Skip to Content
Course content

60: Practice Exercise: Building a Robust Input Validator

Click on the "Edit" button in the top corner of the screen to edit your slide content.

Alright, we've talked about the Scanner class before, but in the real world, users are unpredictable. They'll type "twenty" when you asked for 20, or they'll leave the field blank, or they'll try to enter -500 as their birth year. If we aren't careful, our programs don't just fail—they crash spectacularly with an InputMismatchException.

I want to build a validator for a user's age. It sounds simple, but let's actually try to code it and see where it breaks.

The "Happy Path" that fails

My first instinct is usually to keep it lean. I'll just ask for the age and store it. Here is how I'd start:

Scanner sc = new Scanner(System.in);
System.out.print("Enter your age: ");
int age = sc.nextInt();
System.out.println("You are " + age + " years old.");

This works great if I type 25. But I'm the user now, and I'm feeling chaotic, so I'll type "twenty-five". Boom. InputMismatchException. The program dies instantly. That's not a robust application; that's a fragile one.

Falling into the Infinite Loop trap

Okay, so I need a loop. I'll use hasNextInt() to check if the input is actually a number before I try to grab it. This seems like the logical fix:

System.out.print("Enter your age: ");
while (!sc.hasNextInt()) {
    System.out.println("That's not a number! Try again: ");
}
int age = sc.nextInt();

I run this, I type "abc", and then... nothing happens. Well, not nothing. My console is suddenly screaming "That's not a number! Try again: " a thousand times a second. I've created an infinite loop.

Why? Because hasNextInt() only checks the token; it doesn't consume it. The "abc" is still sitting there in the scanner's buffer. The loop checks it, sees it's not an int, prints the error, and then checks the exact same "abc" again. To fix this, I have to manually clear the "junk" out of the buffer.

while (!sc.hasNextInt()) {
    System.out.println("That's not a number! Try again: ");
    sc.next(); // This consumes the invalid token and clears the way
}
int age = sc.nextInt();

Now the loop actually terminates. We've solved the crashing and the looping, but we've only solved the type problem. We haven't solved the logic problem.

Correct type, impossible value

Now I run the program and enter -150. The program accepts it because -150 is technically an integer. But nobody is negative 150 years old. I need to wrap this in a layer of business logic. I don't want to just check for an integer; I want to check for a valid integer.

I'll wrap the whole thing in a do-while loop. This way, I can check both the type and the value in one go:

int age;
do {
    System.out.print("Enter your age (0-120): ");
    if (sc.hasNextInt()) {
        age = sc.nextInt();
        if (age < 0 || age > 120) {
            System.out.println("Please enter a realistic age.");
        }
    } else {
        System.out.println("Invalid input. Please use numbers.");
        sc.next(); 
    }
} while (age < 0 || age > 120 || !sc.hasNextInt()); // Wait, this logic is getting messy.

Looking at that while condition, I realize I'm repeating myself and it's becoming hard to read. When the logic gets this clunky, it's a signal that I should move the validation into its own method. I don't want to write this loop every single time I need a number in my app.

The Professional Approach: The Helper Method

I'll create a dedicated method that handles the "dirty work" of cleaning the buffer and validating the range. This keeps my main logic clean and makes the validator reusable.

public static int getValidInt(Scanner sc, String prompt, int min, int max) {
    int value;
    while (true) {
        System.out.print(prompt);
        if (sc.hasNextInt()) {
            value = sc.nextInt();
            if (value >= min && value <= max) {
                return value; // Success! Exit the method and return the value
            }
            System.out.println("Error: Value must be between " + min + " and " + max + ".");
        } else {
            System.out.println("Error: Invalid input. Please enter a whole number.");
            sc.next(); // Clear the buffer
        }
    }
}

Now, using this in my main program is a breeze:

int age = getValidInt(sc, "Enter your age: ", 0, 120);
int quantity = getValidInt(sc, "How many items? ", 1, 99);

By abstracting the "try-fail-clear-retry" cycle into a method, we've turned a crash-prone piece of code into a robust utility. We handled the exception (implicitly), managed the buffer, and enforced business rules, all while keeping the main flow of the program readable.




📋 Practical Task

Exercise: The Secure Bank Account Deposit Validator

You are building a banking module that allows users to deposit money into their account. You need to ensure that the deposit amount is valid before it is added to the balance.

Requirements:

  • Create a method called getValidDeposit that takes a Scanner and a String prompt.
  • The method must return a double.
  • The validator must reject:
    • Non-numeric input (e.g., "ten dollars").
    • Negative numbers (you can't deposit negative money).
    • Amounts greater than 10,000.00 (bank policy limits single deposits).
  • If the input is invalid, the program should print a specific error message explaining why it was rejected and prompt the user again.
  • In your main method, call getValidDeposit and print the final accepted amount to the console.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.