How do I keep a Scanner from throwing exceptions when the wrong type is entered?
You can use one of the many hasNext*
methods that Scanner
has for pre-validation.
if (in.hasNextInt()) {
int a = in.nextInt() ;
System.out.println(a);
} else {
System.out.println("Sorry, couldn't understand you!");
}
This prevents InputMismatchException
from even being thrown, because you always make sure that it WILL match before you read it.
java.util.Scanner API
boolean hasNextInt()
: Returnstrue
if the next token in this scanner's input can be interpreted as an int value in the default radix using thenextInt()
method. The scanner does not advance past any input.String nextLine()
: Advances this scanner past the current line and returns the input that was skipped.
Do keep in mind the sections in bold. hasNextInt()
doesn't advance past any input. If it returns true
, you can advance the scanner by calling nextInt()
, which will not throw an InputMismatchException
.
If it returns false
, then you need to skip past the "garbage". The easiest way to do this is just by calling nextLine()
, probably twice but at least once.
Why you may need to do nextLine()
twice is the following: suppose this is the input entered:
42[enter]
too many![enter]
0[enter]
Let's say the scanner is at the beginning of that input.
hasNextInt()
is true,nextInt()
returns42
; scanner is now at just before the first[enter]
.hasNextInt()
is false,nextLine()
returns an empty string, a secondnextLine()
returns"too many!"
; scanner is now at just after the second[enter]
.hasNextInt()
is true,nextInt()
returns0
; scanner is now at just before the third[enter]
.
Here's an example of putting some of these things together. You can experiment with it to study how Scanner
works.
Scanner in = new Scanner (System.in) ;
System.out.println("Age?");
while (!in.hasNextInt()) {
in.next(); // What happens if you use nextLine() instead?
}
int age = in.nextInt();
in.nextLine(); // What happens if you remove this statement?
System.out.println("Name?");
String name = in.nextLine();
System.out.format("[%s] is %d years old", name, age);
Let's say the input is:
He is probably close to 100 now...[enter]
Elvis, of course[enter]
Then the last line of the output is:
[Elvis, of course] is 100 years old
How to stop exception when type in wrong data type using scanner
InputMismatchException from nextInt means the input is not an int. You can catch it.
This will loop until the input is a number between 1 and 6:
do {
try {
guess = sean.nextInt();
if (guess >= 1 && guess <= 6) break;
} catch (InputMismatchException e) {
} finally {
sean.nextLine();
}
System.out.print("Input must be a number between 1 and 6: ");
} while (true);
Side note: calling nextInt will also orphan a new line character, so nextLine advances past it.
Exception Handling with wrong User Input Java
Scanner.nextInt returns ant int, so there is no need to go Object selection = scanner.nextInt()
, and then cast to an int, you can merely have int selection = scanner.nextInt()
and surround that in a try catch that chatches java.util.InputMismatchException
, which is the exception thrown when the user types a letter and not an number
Java.util.scanner error handling
You can use hasNextInt()
to verify that the Scanner
will succeed if you do a nextInt()
. You can also call and discard nextLine()
if you want to skip the "garbage".
So, something like this:
Scanner sc = new Scanner(System.in);
while (!sc.hasNextInt()) {
System.out.println("int, please!");
sc.nextLine();
}
int num = sc.nextInt();
System.out.println("Thank you! (" + num + ")");
See also:
- How do I keep a scanner from throwing exceptions when the wrong type is entered? (java)
The problem with your code, in addition to the unnecessarily verbose error handling because you let nextInt()
throw an InputMismatchException
instead of checking for hasNextInt()
, is that when it does throw an exception, you don't advance the Scanner
past the problematic input! That's why you get an infinite loop!
You can call and discard the nextLine()
to fix this, but even better is if you use the exception-free hasNextInt()
pre-check technique presented above instead.
Java Scanner exception handling
Your program enters an infinite loop when an invalid input is encountered because nextDouble()
does not consume invalid tokens. So whatever token that caused the exception will stay there and keep causing an exception to be thrown the next time you try to read a double.
This can be solved by putting a nextLine()
or next()
call inside the catch
block to consume whatever input was causing the exception to be thrown, clearing the input stream and allowing the user to input something again.
Exception handling in Scanner
Any use of methods that throws exceptions should handle, rethrow, or redeclare (if it is a checked exception) them for the next level up to choose what to do with it.
In Scanner
, if you take nextDouble()
method, it throws various exceptions depending on the status of the scanner. You have to care about it.
But the way to care depend on your program logic.
That said, most exceptions in Scanner
are RuntimeException
, meaning you don't need to explicitly catch them in your code. Assuming you are in a main
, if an exception occurs, it will be handled by at top level by the JVM. I this case, your program will exit with an error code and a stacktrace.
The only exceptions in Scanner
which are checked and that you must handle in some way, is when you construct a Scanner
from a files. IOException
and FileNotFoundException
cannot be ignored.
As an example of (abused) usage of exceptions when you read a double
, you may be tempted to do:
public static void testScanDoubleWithException() {
Scanner sin = new Scanner(System.in);
System.out.println("Enter a double: ");
while (true) {
try {
double d = sin.nextDouble(); // Throw if not a double
System.out.println("Read double value: "+d);
break;
}
catch (InputMismatchException e) {
System.out.println("Invalid double, shoot again:");
sin.nextLine(); // consume bad input
}
}
sin.close();
}
But the Scanner
class provides the more simple/explicit way:
public static void testScanDouble() {
Scanner sin = new Scanner(System.in);
System.out.println("Enter a double: ");
while (!sin.hasNextDouble()) {
System.out.println("Invalid double, shoot again:");
sin.nextLine();
}
double d = sin.nextDouble();
System.out.println("Read double value: "+d);
sin.close();
}
Related Topics
What Is a Covariant Return Type
Possible Heap Pollution via Varargs Parameter
Deserializing into a Hashmap of Custom Objects with Jackson
Parsing Xml with Regex in Java
Run a Single Test Method with Maven
Singleton with Arguments in Java
How to Compile & Run Java Program in Another Java Program
Is the Buildsessionfactory() Configuration Method Deprecated in Hibernate
"Unable to Acquire Application Service" Error While Launching Eclipse
Swing's Keylistener and Multiple Keys Pressed at the Same Time
How to Find the Sum of All the Numbers in an Array in Java
Noclassdeffounderror in Java: Com/Google/Common/Base/Function