在使用Scanner类时遇到一个问题:
1 Exception in thread "main" java.util.NoSuchElementException 2 at java.util.Scanner.throwFor(Unknown Source) 3 at java.util.Scanner.next(Unknown Source)
在执行scanner.next()时遇到异常。Stack Overflow上给出了问题原因与解决办法。
原因:当一个类中两个及两个以上的Scanner实例时,其中一个Scanner类的实例执行scanner.close()方法会关闭其他潜在的InputStream流,导致其他Scanner的扫描器无法读取输入流。
解决办法:对于控制台程序,在程序运行中只注册一个Scanner类的实例从System.in中读取信息。
问题二:使用Scanner#nextInt()时跳过下一个扫描器。
产生原因:在使用Scanner#nextInt()时,nextInt()在遇到 ‘\n‘之前结束,但“\n"会被下一个扫描器所接收,如Scanner#nextLine(),从而直接跳过Scanner#nextLine()。
解决办法:统一使用Scanner#nextLine()代替所有扫描函数。然后进行强制类型转换。
1 String nextIntString = keyboard.nextLine(); //get the number as a single line 2 int nextInt = Integer.parseInt(nextIntString); //convert the string to an int
You close the second Scanner
which closes the underlying InputStream
, therefore the first Scanner
can no longer read from the same InputStream
and a NoSuchElementException
results.
The solution: For console apps, use a single Scanner
to read from System.in
.
Aside: As stated already, be aware that Scanner#nextInt
does not consume newline characters. Ensure that these are consumed before attempting to call nextLine
again by using Scanner#newLine()
.
The nextInt()
method leaves the \n
(end line) symbol and is picked up immediately by nextLine()
, skipping over the next input. What you want to do is use nextLine()
for everything, and parse it later:
String nextIntString = keyboard.nextLine(); //get the number as a single line
int nextInt = Integer.parseInt(nextIntString); //convert the string to an int
This is by far the easiest way to avoid problems--don‘t mix your "next" methods. Use only nextLine()
and then parse int
s or separate words afterwards.
Also, make sure you use only one
Scanner
if your are only using one terminal for input. That could be another reason for the exception.
Last note: compare a
String
with the .equals()
function, not the ==
operator.
if (playAgain == "yes"); // Causes problems
if (playAgain.equals("yes")); // Works every time