简单Java扫描程序问题

简单Java扫描程序问题,java,Java,我学Java的时间不长。在这个脚本中,它说Thread.sleep(10000);您仍然可以键入(我使用eclipse),我真的不知道为什么在我没有uno.nextLine()的情况下,它允许您键入输出;等待10秒之前或之后。请帮忙!谢谢 import java.util.Scanner; class Tutoiral{ public static void main (String args[])throws InterruptedException {

我学Java的时间不长。在这个脚本中,它说Thread.sleep(10000);您仍然可以键入(我使用eclipse),我真的不知道为什么在我没有uno.nextLine()的情况下,它允许您键入输出;等待10秒之前或之后。请帮忙!谢谢

import java.util.Scanner;
class Tutoiral{
        public static void main (String args[])throws InterruptedException {
            Scanner uno = new Scanner(System.in);
            Scanner uno1 = new Scanner(System.in);
            System.out.println("What's your name?");
            String name = uno.nextLine();
            System.out.println("Hi, " + name + ". Feel free to type whatever you want :) BUT DON'T SPAM!!!!!");

            String typed = (": ") + uno1.nextLine();
            System.out.println(name + typed + " (5 types remaining)");
            uno.nextLine();
            System.out.println(name + typed + " (4 types remaining)");
            uno.nextLine();
            System.out.println(name + typed + " (3 types remaining)");
            uno.nextLine();
            System.out.println(name + typed + " (2 types remaining)");
            uno.nextLine();
            System.out.println(name + typed + " (1 type remaining)");
            uno.nextLine();
            System.out.println(name + typed + " (If you type one more time, then I'll... I'll block you! Ha!)");
            uno.nextLine();
            System.out.println(name + typed + " (tut tut tut. You have been blocked for a while for spam. Don't type EVER again ok?)");
            Thread.sleep(10000);
            System.out.println("Ok, you can type again. But I wouldn't If I were you.");
我真的不知道为什么在我没有uno.nextLine()的情况下,它可以让你输入输出

调用
nextLine
将从标准输入读取(并返回)字符。控制台将打印用户输入的字符,无论您是否阅读它们

不幸的是(对您而言),无法阻止用户在标准输入上输入数据


一种解决方法可能是禁用“本地回显”,即避免打印用户输入的字符。我不知道该怎么做。一种讨厌的方法是执行
System.console().readPassword()

为了解决这个问题,我提出了以下非常恶劣的黑客解决方法(注意,例如,
Thread.stop()
,由于很好的原因被弃用):

只需将对
Thread.sleep(10000)
的调用替换为对以下方法的调用:

turnOffLocalEcho(10000);

当调用其
nextSomething()
方法时,uno将在任何时候(睡觉、工作或等待输入时)处理键入的输入。您不需要调用
nextSomething()
并解析输入,但用户可以通过任何一种方式输入。

控制台输入(因此
Scanner
)的工作方式与人们想象的不一样

控制台程序有一个名为的输入流。您可以将其视为程序要读取的字符队列

在控制台程序中键入字符时,通常有两种效果:

  • 终端立即将字符打印到屏幕上
  • 该字符附加到程序的标准输入中。(从技术上讲,这仅在每次键入换行符(Enter)时发生。)
  • 这些操作是由操作系统执行的,因此无论您的程序当前是否正在从stdin读取数据,它们都可以工作。如果程序正在等待数据,它将立即处理它(忽略输入流缓冲)。但是,如果没有(例如,它正在处理其他内容,或者在您的情况下睡眠10秒钟),则该角色将一直坐在队列中,直到程序读取它

    Scanner
    实际上不会提示用户输入一行文本。工作原理:当一个程序试图从stdin读取数据时,如果没有可用的数据,程序将阻塞,直到操作系统向其提供足够的数据
    Scanner.nextLine()。这意味着,
    Scanner.nextLine()
    通常会导致程序等待,直到用户按Enter键

    但是,请注意,如果您一次输入多行文本,例如,通过将多行文本粘贴到终端中,或通过shell管道或重定向(例如使用
    java MyProgram
    ),程序将继续运行,直到吃掉所有输入

    当您的程序处于睡眠状态时,用户仍然可以键入并附加到程序的stdin!(尝试在程序末尾添加一些
    System.out.println(name+typed+uno.nextLine());
    副本,看看在程序睡眠时键入时会发生什么。)

    因此,为了防止用户键入主程序将读取的内容,您需要在主线程睡眠时执行两项操作:

  • 告诉控制台停止回显键入控制台的字符
  • 读取输入到stdin的所有字符,并丢弃它们
  • 您可以通过在另一个线程中调用
    System.console().readPassword()
    (并放弃其输出)来完成这两项任务。这样,在10秒后,您的主线程将唤醒并终止密码读取线程。但到那时,用户在主线程睡眠时键入的任何内容都将被另一个线程读取(从stdin中删除)并丢弃,因此实际上用户无法在控制台上键入。(有关此代码,请参见aioobe的答案。)

    turnOffLocalEcho(10000);