Using a java.util.Scanner from within a method causes a runtime error

一笑奈何 提交于 2020-01-05 08:17:21

问题


Why would the following code give me a runtime error? It gives me a NoSuchElementException when the method is called the second time. It works fine if I delete the call to stdin.close(), but then Eclipse gives a warning that the resource is not closed.

Code:

import java.util.Scanner;


public class st {
  public static void main(String[] args) {
    System.out.println("First call");
    getInt("Enter first int (1-10): ");
    System.out.println("Second call");
    getInt("Enter second int (1-10): ");
  }

  /**
   * Reads an integer number from the keyboard.
   *
   * @param  prompt    the string to display as a prompt.
   * @return           the integer number entered at the keyboard.
   */
  public static int getInt(String prompt) {
    Scanner stdin = new Scanner(System.in);

    System.out.print(prompt);
    int val = stdin.nextInt();

    stdin.close();
    return(val);
  }
}

// END

Output:

>java st
First call
Enter first int (1-10): 5
Second call
Enter second int (1-10): Exception in thread "main" java.util.NoSuchElementException
        at java.util.Scanner.throwFor(Unknown Source)
        at java.util.Scanner.next(Unknown Source)
        at java.util.Scanner.nextInt(Unknown Source)
        at java.util.Scanner.nextInt(Unknown Source)
        at st.getInt(st.java:24)
        at st.main(st.java:9)

>

Version:

>java -version
java version "1.7.0_21"
Java(TM) SE Runtime Environment (build 1.7.0_21-b11)
Java HotSpot(TM) 64-Bit Server VM (build 23.21-b01, mixed mode)

>

Thanks

Brian


回答1:


AS @MikePrecup says, when you close the first Scanner (stdin), you are also closing System.in, therefore the second Scanner can no longer read from it and a NoSuchElementException is thrown.

However, I would suggest another option: use a single scanner declaring it as a class variable.

public class st {

  private static Scanner stdin = new Scanner(System.in);

  public static void main(String[] args) {
    System.out.println("First call");
    getInt("Enter first int (1-10): ");
    System.out.println("Second call");
    getInt("Enter second int (1-10): ");
  }

  /**
   * Reads an integer number from the keyboard.
   *
   * @param  prompt    the string to display as a prompt.
   * @return           the integer number entered at the keyboard.
   */
  public static int getInt(String prompt) {
    System.out.print(prompt);
    int val = stdin.nextInt();

    stdin.close();
    return(val);
  }
}

// END



回答2:


The problem is that closing stdin also closes the underlying stream, which is, in this case, System.in. Hence, you won't be able to get any more input from it. You'll need to prevent it from closing. The easiest option is probably to wrap System.in with a CloseShieldInputStream.



来源:https://stackoverflow.com/questions/17256945/using-a-java-util-scanner-from-within-a-method-causes-a-runtime-error

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!