Java Scanner读取输入报NoSuchElementException异常排查
问题背景
程序预期实现功能:接收用户输入的两个整数、一个由逗号分隔数字组成的字符串,输出字符串中可同时被这两个整数整除的元素的索引位置。代码运行时在main方法第9行nextInt()调用位置抛出java.util.NoSuchElementException异常。
异常栈信息
Exception in thread "main" java.util.NoSuchElementException at java.util.Scanner.throwFor(Scanner.java:862) at java.util.Scanner.next(Scanner.java:1485) at java.util.Scanner.nextInt(Scanner.java:2117) at java.util.Scanner.nextInt(Scanner.java:2076) at Main.main(Main.java:9)
原实现代码
import java.util.Scanner; class Main { public static void main(String args[]) { System.out.println("This program receives an integer vector and checks if it has any element divisible by N and M."); System.out.println("Note that you should only enter numbers (do not use any letter or space) otherwise the execution will be terminated."); Scanner sc = new Scanner(System.in); Scanner scString = new Scanner(System.in); System.out.print("Enter an integer value for N: "); int n = sc.nextInt(); System.out.print("Enter an integer value for M: "); int m = sc.nextInt(); //sc. nextLine(); System.out.println("Please enter your vector elements (comma separated) below."); String str = scString.nextLine(); String[] arrOfStr = str.split(",", 0); int i=0; for (String a : arrOfStr){ int x = Integer.parseInt(a); if(x%n ==0 && x%m == 0){ break; } i=i+1; } System.out.print("Element "+i+" of the entered vector is divisible by both "+n+" and "+m); } }
问题产生原因
- 直接触发异常的原因:代码同时创建了两个绑定
System.in标准输入流的Scanner对象。两个独立Scanner会各自维护输入流的读取位置和缓冲区,互相不会同步读取状态,当其中一个Scanner预读取了流中内容后,另一个Scanner尝试读取时会判定流中没有可读取内容,直接抛出NoSuchElementException。 - 代码还存在两个隐藏逻辑缺陷:
- 调用
nextInt()读取整数时,只会读取数字本身,不会消费数字后面输入的换行符,如果不手动调用一次nextLine()消费残留换行,后续读取字符串的操作会直接读到空内容。 - 原循环逻辑只会返回第一个匹配元素的索引,遇到第一个符合条件的元素就直接跳出循环;如果数组中没有任何元素符合整除条件,最终输出的索引值等于数组长度,属于无效索引,会误导用户。
- 调用
修复后正确代码
修复点说明:
- 删除多余的Scanner实例,所有输入操作复用同一个Scanner对象,避免多实例抢占输入流的问题
- 读取完两个整数后,主动调用
nextLine()消费残留的换行符 - 优化遍历逻辑,遍历全量数组收集所有符合条件的索引,无匹配时给出明确提示
- 增加
trim()处理兼容用户输入时不小心夹带的空格
import java.util.Scanner; class Main { public static void main(String args[]) { System.out.println("This program receives an integer vector and checks if it has any element divisible by N and M."); System.out.println("Note that you should only enter numbers (do not use any letter or space) otherwise the execution will be terminated."); Scanner sc = new Scanner(System.in); System.out.print("Enter an integer value for N: "); int n = sc.nextInt(); System.out.print("Enter an integer value for M: "); int m = sc.nextInt(); // 消费读取整数后残留的换行符 sc.nextLine(); System.out.println("Please enter your vector elements (comma separated) below."); String str = sc.nextLine(); String[] arrOfStr = str.split(",", 0); StringBuilder matchIndexes = new StringBuilder(); for (int i = 0; i < arrOfStr.length; i++) { int x = Integer.parseInt(arrOfStr[i].trim()); if(x % n == 0 && x % m == 0){ matchIndexes.append(i).append(" "); } } if (matchIndexes.length() == 0) { System.out.printf("No element of the entered vector is divisible by both %d and %d%n", n, m); } else { System.out.printf("Index of elements divisible by both %d and %d: %s%n", n, m, matchIndexes.toString().trim()); } sc.close(); } }
内容的提问来源于stack exchange,提问作者Hash Blog
相关产品推荐
相关产品推荐

