The first place you should always go when you have unexpected behavior is the documentation. scan.nextInt()
only consumes the input if it can be translated to an integer. Otherwise it leaves it in the scanner's buffered data. So if the user enters a letter, that letter is never consumed, scan.nextInt()
just keeps reading that same letter over and over and, because it's not an integer, it keeps looping. The fix is to simply read the input from the scanner as a string, whether it can be interpreted as an integer or not. Then you can check if it's an integer yourself, and the input is already consumed. Here's your example, modified:
Scanner scan = new Scanner(System.in);
int input;
boolean check = false;
do {
try {
System.out.println("give me a number: ");
// This retrieves the next line of input, without converting it to an integer:
String line = scan.nextLine();
// This tries to convert it to an integer,
// and throws a NumberFormatException if it can't:
input = Integer.parseInt(line);
check = true;
} catch (NumberFormatException e) {
System.out.println("Eingabe ist falsch");
}
} while (!check);
System.out.println("getout");
In order to try to help you visualize my explanation, I'm going to write out a sample input and then I'll show where the data is at each step. Let's say I enter abc
into the console, using your original code. The program then enters into an infinite loop, and here's why:
I enter abc
into the input stream:
System.in: abc
scan:
input:
scan
reads abc
from the input stream as it tries to find an integer:
System.in:
scan: abc
input:
scan
can't translate abc
into an integer, so it throws an exception. But note that scan
held on to abc
, it doesn't just go away:
System.in:
scan: abc
input:
The same thing happens again, it tries to convert abc
to an integer, but it can't, so it throws an exception again. See the infinite loop happening?
System.in:
scan: abc
input:
Now lets try my code. I'll enter abc
and then 123
:
I enter abc
into the input stream:
System.in: abc
scan:
line:
input:
scan
reads abc
from the input stream because I told it to read the next line:
System.in:
scan: abc
line:
input:
scan
passes the data on to line
, because it matches the criteria for a line of text:
System.in:
scan:
line: abc
input:
The code tries to parse abc
into an integer, but it can't, so it goes to the next loop iteration. line
is local to each iteration of the loop, so its old value gets thrown out:
System.in:
scan:
line:
input:
I enter 123
into the input stream:
System.in: 123
scan:
line:
input:
scan
reads 123
from the input stream because I told it to read the next line:
System.in:
scan: 123
line:
input:
scan
passes the data on to line
, because it matches the criteria for a line of text:
System.in:
scan:
line: 123
input:
The code successfully parses 123
into an integer, and assigns it to input
. No infinite loop, the program has completed.
System.in:
scan:
line:
input: 123