Java Scanner不等待输入

Hou*_*ini 4 java user-input java.util.scanner

我这里有两个代码块.一个扫描仪正确地等待用户输入,另一个扫描仪正好通过它并且调用nextInt()返回一个NoSuchElementException.这是有效的块:

public void startGame() {
   out.println("Player1: 1 for dumb player, 2 for smart player, 3 for human player.");
   Scanner scan = new Scanner(System.in);
   p = scan.nextInt();

   if (p == 1)
        p1 = new DumbPlayer("ONE");
   if (p == 2)
        p1 = new SmartPlayer("ONE");
   else 
       p1 = new HumanPlayer("ONE");

   out.println("Player2: 1 for dumb player, 2 for smart player, 3 for human player.");
   p = scan.nextInt();

   if (p == 1)
        p2 = new DumbPlayer("TWO");
   if (p == 2)
        p2 = new SmartPlayer("TWO");
   else 
        p2 = new HumanPlayer("TWO");

   scan.close();
Run Code Online (Sandbox Code Playgroud)

这里的块不是:

public int findBestMove(Set<Integer> moves, Board b) {

    Set<Integer> set = new HashSet<Integer>();

    out.println("Player " +name+ ", select a column from 1-7: ");
    Scanner scan = new Scanner(System.in);  <--here it should wait for input, but does not!
    int move = scan.nextInt();   <-- NoSuchElementException
    scan.close();

    for (int x = 1; x <= 7; x++) {
        set.add(move);
        move += 7;
    }
    ....etc
Run Code Online (Sandbox Code Playgroud)

这两个都是单独的类,并且在另一个类中从main方法调用.基本上是main()调用startGame(),它反过来调用findBestMove()某些Player类的方法......这是非工作代码所在的位置.在程序中是否有时候不适合接受输入?我的印象是,无论何时我想要用户输入,我都可以使用这种方法.谢谢!

Den*_*kiy 6

nextInt()不会\n在流中丢弃,因此下一个调用什么也找不到.您必须使用Scanner.skip("\n")或手动跳过它Scanner.nextLine()

编辑后发现"跳过readInt()"意味着代码抛出异常.在@Andreas的帮助下,这是另一种解决方案.在java6中,添加了一个新类Console,用于为stdin提供更好的接口.它会返回一个不关心你关闭它的读者.所以下面的代码段工作得很好:

    Scanner fi = new Scanner(System.console().reader());
    System.out.println(fi.nextInt());
    fi.close();

    fi = new Scanner(System.console().reader());
    System.out.println(fi.nextInt());
    fi.close();
Run Code Online (Sandbox Code Playgroud)


And*_*ter 5

根据java.util.Scanner javadocScanner.close()如果此流实现了Closeable接口,则关闭关联的流。java.lang.System.in是一个InputStream,它实现了Closeable接口。因此,在调用与 关联的Scanner.close()a之后,流将关闭并且不再可用。ScannerSystem.inSystem.in

以下 SSCCE 对我有用。我从问题中删除了一些与实际问题无关的代码。请注意,使用这种方法,虽然它有效,但 Eclipse 会给我警告"Resource leak: 'scan' is never closed",因此更好的解决方案是仅使用一个 Scanner 实例。

package com.example;

import java.util.Scanner;
import java.util.Set;
import static java.lang.System.out;

public class ScannerTest {
    int p = 0;
    String name = "Test";

    public void startGame() {
        out.println("Player1: 1 for dumb player, 2 for smart player, 3 for human player.");
        Scanner scan = new Scanner(System.in);
        p = scan.nextInt();

        out.println("Result1: " + p);

        out.println("Player2: 1 for dumb player, 2 for smart player, 3 for human player.");
        p = scan.nextInt();

        out.println("Result2: " + p);

        // scan.close();   // Do not close the Scanner to leave System.in open
    }

    public int findBestMove(Set<Integer> moves, Object /*Board*/ b) {
        out.println("Player " +name+ ", select a column from 1-7: ");
        Scanner scan = new Scanner(System.in);
        int move = scan.nextInt();
        // scan.close();   // Do not close the Scanner to leave System.in open

        out.println("Move: " + move);

        return 0;
    }

    public void run() {
        startGame();
        findBestMove(null, null);
    }

    public static void main(String[] args) {
        ScannerTest st = new ScannerTest();
        st.run();
    }
}
Run Code Online (Sandbox Code Playgroud)