2013-11-04 119 views
8

我有如下所示创建多个整数对象到链表一类:Java的多台扫描仪

public class Shares<E> implements Queue<E> { 
protected LinkedList<E> L; 


public Shares() { 
    L = new LinkedList<E>(); 
} 

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; 
} 

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

public class Application { 
private static Scanner scan; 

public static <E> void main(String[] args) { 
    Queue<Integer> S = new Shares<Integer>(); 
    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(); 
    } 
} 

}

的appliation应该允许用户输入他们的愿望,但错误“没有行发现”,“添加”多次后出现add方法已被调用。

我猜这是因为该方法中的扫描仪尚未关闭,然后在需要时重新打开。这是什么错误的程序,如果是的话,我将如何去解决它?

请注意这个程序没有完成,因为我将添加销售这些股票的销售方法,这就是为什么我使用while循环的原因。

+0

在S.add中,您可能会遇到与调用扫描器相关的问题? –

回答

10

对于任何流有多个包装是一个真正混淆你自己的好方法。我建议你除非真的知道自己在做什么,否则只能打包一次。

要做到这一点,最简单的办法就是在这种情况下使用单,因为它包装另一个单(最好是周围的扫描仪作为参数传递)

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 <E> void main(String[] args) { 

即时猜测这是因为该方法中的扫描器尚未关闭

一旦关闭流,它将关闭底层流并且不能再次使用它。只有关闭System.in才能防止再次使用它。

我该如何解决它?

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


顺便说一句,不要退出程序没有解释。调用System.exit(0);甚至没有错误信息也是一场噩梦。我曾经在一个有260个调用System.exit()的项目上工作,而且经常没有错误信息,您可以想象诊断服务器有多么有趣,因为没有明显的原因。

4

第一错误是这行代码

scanInt.close(); 

关闭System.in,而不仅仅是scanInt对象。这意味着在第一次添加调用之后,扫描对象将只消耗它已有的输入,然后您将收到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 

但是,我会同意彼得,你不应该使用多个包装。考虑将“扫描器”对象作为参数传递给Shares类承包商。

0

有多个扫描仪(在同一个流)是一个非常糟糕的做法,因为扫描仪消耗他们共享的流。

在调试源代码,并在寻找Scanner类,我发现我已经验证:

  • 到源输入流
  • 用于保存输入内部专用缓冲区的参考。

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

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

很明显,其他扫描仪的状态变得损坏(无效)。

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