Java多个扫描仪

我有一个类创建多个Integer对象并将它们放入LinkedList ,如下所示:

 public class Shares implements Queue { protected LinkedList L; public Shares() { L = new LinkedList(); } public boolean add(E price) { System.out.println("How many of these shares would you like?"); Scanner scanInt; scanInt = new Scanner(System.in); Integer noShares = scanInt.nextInt(); for (int i = 0; i < noShares; i++) { L.addLast(price); } scanInt.close(); return true; } } 

我有一个应用程序从控制台扫描输入“添加”,如果找到,调用方法add如下所示:

 public class Application { private static Scanner scan; public static  void main(String[] args) { Queue S = new Shares(); scan = new Scanner(System.in); System.out.println("Please type add"); String sentence = scan.nextLine(); while (sentence.equals("quit") == false) { if (sentence.equals("add")) { System.out .println("What price would you like to buy your shares at?"); S.add((Integer) scan.nextInt()); } else System.exit(0); sentence = scan.nextLine(); } } } 

应用程序应允许用户根据需要多次输入“添加”,但在调用add方法后出现错误“no line found”。

我猜这是因为方法中的Scanner尚未关闭,然后在需要时重新打开。 这是程序的错误,如果是这样,我将如何修复它?

请注意,此计划尚未完成,因为我将添加销售这些股票的销售方法。 这就是我使用while循环的原因。

拥有任何流的多个包装器是真正让自己迷惑的好方法。 除非你真的知道自己在做什么,否则我建议你只包一次流。

最简单的方法是在这种情况下使用单例,因为它包装了另一个单例(最好是将Scanner作为参数传递)

 public class Application { // use this Scanner in all you other code, don't create another one. static final Scanner scan = new Scanner(System.in); public static  void main(String[] args) { 

我猜这是因为该方法中的扫描仪尚未关闭

关闭流后,它会关闭基础流,您无法再次使用它。 如果要阻止再次使用它,请仅关闭System.in。

我该怎么办呢?

最好的解决方案是让所有扫描仪在一个地方,一个方法或一个类中使用。 您让main()与用户进行所有交互,并将值传递给数据结构。 拥有自我初始化的对象是一个不好的做法,如果你开始这样做,它将困扰你的余下的开发日;)(严重的是你会看到这一次又一次完成,它往往是一场噩梦)


BTW如果没有解释,切勿退出程序。 调用System.exit(0); 甚至没有错误信息也是一场噩梦。 我曾经做过一个项目,它有260个调用System.exit(),通常没有错误信息,你可以想象诊断一个服务器只是停止没有明显原因是多么有趣。

第一个错误是这行代码

 scanInt.close(); 

关闭System.in,而不仅仅是scanInt对象。 这意味着在第一次调用add之后,scan对象只会消耗它已有的输入,然后你会收到NoSuchElementException: 删除这一行。

现在,如果你用这个替换你的最后一行

 sentence = scan.nextLine(); System.out.println("sentence: \"" + sentence + "\""); 

你会看到退出前得到的最后一个输入是一个空字符串。 因此,在下一个循环中输入else语句,程序将停止执行。 您可以通过添加以下内容来解决此问题:

 scan.nextLine(); // consume the first always empty String... System.out.println("Please type add"); sentence = scan.nextLine(); // and then get the actual value 

但是,我同意彼得你不应该使用多个包装器。 考虑将Scanner对象作为Shares类承包商中的参数传递。

有多个扫描程序(在同一个流上)是一种非常糟糕的做法,因为扫描程序会使用它们共享的流。

我已经validation了调试源代码并查看我发现的Scanner类:

  • 对源输入流的引用
  • 用于保存输入的内部私有缓冲区。

因此,当扫描程序实例使用其流时,基本上它只读取一堆字节(1024)并且流的位置向前移动。

例如,当nextLine()方法是invoket时,在幕后, source.read()将结果复制到私有缓冲区中。

显然,其他扫描仪的状态已损坏(无效)。

尝试自己调试Java源代码和/或查看Scanner.readInput()方法。