Scanner類throwFor(Unknown Source)及跳過下一個掃描器分析


在使用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 ints 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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM