The Scanner Class for Input
Scanner read methods throw an exception when they cannot return a value that matches the request.
Why Input Reads Can Fail
Suppose a program asks the user for a number and then reads it with a Scanner. Most of the time the user types what the program expects, and the read succeeds. But input is not under the program's control. The user might type a word where a number belongs, or the input might run out before the program has asked for everything it needs. Java's Scanner class has a defined response to both situations: it throws an exception.
This article follows what happens to the Scanner's position in the input at each step, so you can predict which call will fail and which exception will appear. The core idea is simple: a Scanner read method either returns a value that matches the request, or it throws an exception. The rest of the article shows exactly when each of those outcomes happens.
The Scanner's Place in the Input
Think of the Scanner as holding a place in a stream of input. Each read method looks at the next token, which is the piece of input the Scanner will consider next. If that token fits the type the method asked for, the method returns a value and the place moves forward past it.
If the input has no tokens left, or the next token does not fit the requested type, the method cannot return a value, and it throws an exception instead. The two exceptions covered here are the two ways a read can go wrong. They correspond to two different questions the Scanner asks: is there anything left to read, and does what is there match what was requested?
Reading Past the End of Input
NoSuchElementException is thrown when an attempt is made to read past the end of input. This failure does not depend on what the input looks like. It depends only on the fact that the input has run out. If the Scanner has already consumed every token, any further read attempt fails this way, no matter what type the caller requested.
NoSuchElementException means there is no token left for the read to examine. The type requested does not matter at that point.
Input: 3 9
The first two reads return 3 and 9. The third read finds no tokens left and throws NoSuchElementException.- The program asks for three integers, but only two are provided.
- The third
nextInt()call has no token to examine, so the input-exhausted failure occurs.
Notice that the third read in this example fails even though the program only needs an int. The reason is not the type. The reason is that nothing remains in the input. The same logic applies to any read method: if the input is exhausted, the call cannot return a value.
A Token That Does Not Fit
InputMismatchException is thrown when the next token does not represent a value of the requested type, and the mismatched token is not consumed. The key word is next. The method does not skip ahead to find a matching value. It looks only at the token that comes next.
Input: 7 apples
The first read returns 7. The second read encounters apples, which is not an integer, and throws InputMismatchException. The word apples was not consumed.- The first read succeeds, so the place in the input moves past 7.
- The second read fails at the second call, not the first.
- Because apples was not accepted, it is still the next token the Scanner would examine.
Because the failing token is not consumed, it remains the next token the Scanner would look at. This is why a program that catches this exception and tries the same integer read again without changing the input will see the same word again and fail again. The token has to be dealt with, not just retried.
Telling the Two Failures Apart
The two exceptions are reached by different checks, and the checks happen in a fixed order. First the Scanner checks whether any tokens remain. If none remain, the call ends with NoSuchElementException. If a token remains, the Scanner checks whether that token represents a value of the requested type. If it does not, the call ends with InputMismatchException. Only when both checks pass does the call return the value.
Read the flowchart as a rule for prediction. Before you assume a read will succeed, ask two questions in order: is there still a token to read, and does that token fit the type being requested? A no at the first question gives NoSuchElementException. A no at the second gives InputMismatchException.
Compare the two examples. In the apples example, a token was present but the wrong kind, so the failure was a mismatch. In the 3 9 example, no token was present when the third read happened, so the failure was reading past the end of input. Both failures happen during a read call, but the checks send them down different branches.
Mistakes When Reading Scanner Input
Common mistake Assuming the type is the reason a read fails when the input is simply empty
What it looks likeReading a third int from input that contains only two numbers
Why it failsIf the input has no tokens left, the failure is
NoSuchElementExceptionregardless of the type requested.Do this insteadAsk first whether a token remains. If none does, the cause is an exhausted input.
Common mistake Expecting the Scanner to skip a bad token and find the next matching value
What it looks likeReading an int from 7 apples 9 and expecting 9 to be returned
Why it failsThe method looks only at the next token. A token that does not fit causes
InputMismatchExceptionand is not consumed.Do this insteadHandle the non-matching token explicitly, since the Scanner will not move past it on its own.
Common mistake Retrying the same read after catching InputMismatchException without changing the input position
Why it failsThe mismatched token was not consumed, so the same token is the next one examined.
Do this insteadDeal with the token before reading again, so the next token is different.
Handling Is Not Mandatory
The source states that the exceptions generated by these Scanner methods do not require mandatory exception handling. A program that calls these methods is not forced by the rules of the language to surround each read with a try block. The source describes the exceptions as something that can occur, not as something the caller must declare or catch in order to compile.
Predict the Failing Read
What do you think happens?
The input is the line 3 9. The program calls nextInt() three times in a row. Which call fails, and with which exception?
Reveal answer
The third call fails, with NoSuchElementException.
The first two calls read 3 and 9. When the third call runs, no tokens remain, so the Scanner reads past the end of input.
The input is the line 4 five 6. The program calls nextInt(), then nextInt(), then nextInt(). Trace each call. Which call fails, which exception is thrown, and what is the next token the Scanner would examine afterward?
Hints
- Ask first whether a token remains for each call.
- Then ask whether that token is an integer.
- A token that causes a mismatch is not consumed.
Key Takeaways
- A Scanner read method either returns a value matching the request or throws an exception.
NoSuchElementExceptionis thrown when a read tries to go past the end of input, regardless of the requested type.InputMismatchExceptionis thrown when the next token does not fit the requested type, and that token is not consumed.- Checking whether a token remains comes before checking its type, which is how to tell the two failures apart.
- The source states these exceptions do not require mandatory exception handling, but a failed read still needs a deliberate response.