Вызов nextInt()
(или любой метод next()
) просто попытается прочитать следующий токен (в приведении nextInt()
, возможный знак (+/-) и цифры) в потоке, например: стандартный ввод.
Если вы введете: 0 1 2, то при каждом последующем вызове nextInt()
будут возвращаться 0, 1 и 2.
Чтобы продолжить с Scanner
, вам не нужно создавать Scanner
каждый раз, когда вызывается метод reAsk
, и вам не нужно использовать рекурсию в таком тривиальном случае (если только это не упражнение ): вы можете использовать его повторно, но вы должны быть осторожны с символами, оставленными в буфере в случае ошибок.
Например:
Scanner sc = new Scanner(System.in);
try {
...
int select;
for (;;) {
try {
select = sc.nextInt();
break;
} catch (InputMismatchException ignored) {
continue;
}
}
// select is always initialized in that case
switch (select) {
...
}
}
Это сделает бесконечный цикл, потому что sc
не может прочитать int
и в буфере все еще есть недопустимый символ int
(например: 'a 1'
).
Вы можете использовать sc.next()
для продвижения (это отбросит следующий токен, например: a
в приведенном выше примере).
Но было бы разумнее использовать sc.hasNextInt()
в этом случае:
Scanner sc = new Scanner(System.in);
while (!sc.hasNextInt() && sc.hasNext()) {
sc.next(); // advance / discard the invalid token
}
// we don't care about result of hasNext() here.
int select = sc.nextInt();
Как сказано в комментарии выше, мы не тестируем hasNext()
по двум основным причинам:
- если
hasNext()
возвращает false
, то более вероятно, что поток закончился. Возможно, вы захотите вызвать hasNextInt()
до nextInt()
, и если он вернет false
, правильно завершите ваш метод. В этом примере произойдет сбой с NoSuchElementException
.
System.in
вероятно закончится, только если он будет перенаправлен (например: java Main < foobar.txt
, echo a | java Main
) или если будет вызвана какая-то последовательность (я не помню, но я верю, что это Ctrl + Z) или если вы закрыли (в) непосредственно в Java (System.in.close()
).
Примечание: в большинстве случаев такие ресурсы, как Scanner
, создаются в try-with-resources , например:
try (Scanner sc = new Scanner(System.in)) {
...
}
Хотя это хорошая практика, это закроет System.in
, и вы никогда не сможете его использовать:
try (Scanner sc = new Scanner(System.in)) {
String next = sc.next(); // again, without hasNext().
}
try (Scanner sc = new Scanner(System.in)) {
String next = sc.next(); // fail NoSuchElementException (stream is closed).
}
В вашем случае вы можете игнорировать try-with-resources .