In the hasNext
and hasNextXxx
methods of java.util.Scanner
it reads:
Returns true if this scanner has another token in its input. This method may block while waiting for input to scan. The scanner does not advance past any input.
How can the scanner not advance through the input stream while it clearly has to check if a next token is present in the input (as Readable
or InputStream
)?
There are two notions of "advancing through input" being conflated here.
The first notion is reading more bytes from the InputStream, which of course the Scanner has to do in order to test whether it has a next token. The Scanner does this by buffering the new bytes read from the InputStream, so that those bytes can later be read from the Scanner when necessary. We could call this "advancing through the input stream".
The second notion is advancing the position of the next byte to be consumed from the buffer. This happens when you call methods like next
which consume tokens, to mark that those bytes have been "used" and shouldn't be read again; calling next
advances the position in the buffer. We could call this "advancing through the input in the Scanner's buffer".
The documentation's statement "The scanner does not advance past any input" is the second notion; calling hasNext
doesn't advance through the Scanner's buffer, it merely reads more bytes from the input stream into the buffer. To verify this, you can try creating an input stream, calling hasNext
, and then reading the next character (rather than the next token) using nextInLine
:
> InputStream is = new ByteArrayInputStream("hello world".getBytes());
> Scanner sc = new Scanner(is);
> sc.next()
"hello" (String)
> sc.hasNext()
true (boolean)
> sc.nextInLine(".")
" " (String)
So calling hasNext
not only doesn't consume the next token, but it also doesn't consume the delimiter before the next token. The Scanner has not "advance[d] past any input" in this sense.