2013-11-04 168 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()