在使用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
補充:在使用Scanner#hasNextInt(),hasNextDouble()...函數時,如果返回值為false則應該在else語句中增加Scanner#nextLine()以抵消 '\n'。
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 \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