Java:使用Scanner时始终收到NoSuchElementException的解决方法

3

我有这段简单的代码:

    public class Example {
       public Example() {
          Scanner scanner = new Scanner(System.in);
          int row = scanner.nextInt();   // exception at this line
          scanner.close();
       }

    public static void main(String[] args) {
        Example ex1 = new Example();   // this line successfully operate
        Example ex2 = new Example();   // exception : no such element exception at above line
    }
  }

我不知道为什么每次代码运行到ex2时都会收到这个异常。


2
那段代码甚至无法编译。请不要在这个网站上发布“几乎”代码,而是只发布真正的代码。 - Hovercraft Full Of Eels
@HovercraftFullOfEels 抱歉,我已经编辑了我的代码。我的完整代码很长,我手动重新输入到这个网站上,所以发现了很多错误 :) - hqt
谢谢你的更正。@Issam似乎已经回答了你的问题。 - Hovercraft Full Of Eels
如果您在 Google 上搜索“使用 Scanner 读取用户输入”,您会发现在 0.001 秒内有数百万个结果向您呼喊。 - Rohit Jain
2个回答

4
问题出在你关闭了Scanner,这也导致底层的InputStream(在这种情况下是stdin)被关闭。当你再次尝试使用stdin时,Scanner无法检索到任何数据,因为stdin已经关闭。
如果直接从命令行运行,则提供对stdin访问的正确方式是使用Console类。控制台类提供了一个包装在stdin周围的Reader,它具有无操作关闭方法。例如:
public class Example {
   public Example() {
      Scanner scanner = new Scanner(System.console().reader()); 
      // note change on above line
      int row = scanner.nextInt();
      scanner.close();
   }
}

请注意,如果您通过Console类以外的方式访问stdin,则可能会给自己带来问题。如果您不是直接从命令行调用Java程序,则无法访问控制台。例如,以下调用将会引起问题。
echo 2 3 | java Example

或者
Process p = new ProcessBuilder("java", "Example").start();
// write data to process

@IMustBeSomeone Stdin是一个通用的输入流名称,所有程序都可以使用。在Java中,System.in是表示stdin的特定对象。 - Dunes

4

在调用scanner.nextInt()之前应该添加if(Scanner.hasNext());因为没有找到要读取的整数而导致异常。


3
应该是hasNextInt()hasNextXXX()应该与nextXXX()对应。但是因为你的概念是正确的,所以加1。 - Hovercraft Full Of Eels
如果没有要读取的整数,下一步应该尝试什么?为什么当我创建另一个对象时,会出现这个错误?(第一次创建ex1时没有出现)。谢谢 :) - hqt
1
当您关闭第一个扫描仪时,实际上发生的情况是,您也关闭了stdin,正如扫描仪关闭方法(http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Scanner.html)中所述,因此第二个扫描仪将无法工作。 - James from CppDepend Team
这意味着我们不应该像上面的例子那样关闭扫描器吗? - hqt
1
更好的方法是使用一个扫描器实例,并在主方法结束时关闭它。不需要使用两个扫描器。 - James from CppDepend Team

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接