在使用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()在遇到 ' '之前结束,但“ "会被下一个扫描器所接收,如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
补充:在使用Scanner#hasNextInt(),hasNextDouble()...函数时,如果返回值为false则应该在else语句中增加Scanner#nextLine()以抵消 ' '。
1 public void showMenu() { 2 System.out.println("****************************"); 3 System.out.println("Option Menu"); 4 System.out.println("1、登录"); 5 System.out.println("2、注册"); 6 System.out.println("3、退出"); 7 System.out.println("请选择:"); 8 System.out.println("****************************"); 9 if (scanner.hasNextInt()) { 10 int index = Integer.parseInt(scanner.nextLine()); 11 choice(index); 12 } else { 13 scanner.nextLine(); 14 System.out.println("请输入数字..."); 15 showMenu(); 16 } 17 }
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
(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