簡體   English   中英

Java 使用帶有 try-with-resources 的掃描儀

[英]Java using scanner with try-with-resources

我有兩個版本的 Java 代碼獲取用戶輸入直到用戶鍵入“q”版本 1:

public class Test {
    public static void main(String[] args) {
        String input = "";
        while (!input.equals("q")) {
            Scanner scanner = new Scanner(System.in);
            System.out.print("Input: ");
            input = scanner.nextLine();
            System.out.println("Input was: " + input);
        }
    }
}

版本 2:

public class Test {
    public static void main(String[] args) {
        String input = "";
        while (!input.equals("q")) {
            try(Scanner scanner = new Scanner(System.in)){
                System.out.print("Input: ");
                input = scanner.nextLine();
                System.out.println("Input was: " + input);
            }
        }
    }
}

版本 1 按預期工作,但版本 2 不按預期工作。 即在第一次讀取用戶輸入后,會產生錯誤

Input: 12
Input was: 12Exception in thread "main" 
Input: java.util.NoSuchElementException: No line found
    at java.util.Scanner.nextLine(Scanner.java:1540)
    at RealEstateCompany.main(RealEstateCompany.java:115)

我的猜測是因為版本 2 使用 try with resource 所以它在使用后關閉掃描器並且導致錯誤?

提前謝謝你的幫助!

[更新] 版本 3:

public class Test {
    public static void main(String[] args) {
        String input = "";
        try(Scanner scanner = new Scanner(System.in)){
            while (!input.equals("q")) {
                System.out.print("Input: ");
                input = scanner.nextLine();
                System.out.println("Input was: " + input);
            }
        }
    }
}

第 3 版有效。 但是,為什么版本 3 可以,而版本 2 不行呢?

在我的評論中添加更多細節

try-with塊定義如下:

try(...) {
   ...
}

括號中的參數需要是java.lang.AutoCloseable的實例。 一個例子是類java.io.InputStream ,它也是System.in的類。

try-with嘗試自動關閉其提供的資源。 根據使用的資源,它還會關閉所有子資源。

舉個例子,你try(Scanner scanner = new Scanner(System.in)) ,它使用Scanner作為資源。 掃描程序本身使用System.in作為資源。 一旦try塊被保留(當達到}時,它會嘗試關閉其資源,即Scanner實例。 此實例還嘗試關閉資源System.in

一旦System.in關閉,你就不System.in從控制台獲得任何輸入(至少沒有一些額外的工作,我認為......)。

具體來說,在你的第二個例子中:

while (!input.equals("q")) {
    try(Scanner scanner = new Scanner(System.in)){
            ...
    }  // <--- The block is left, scanner is closed, System.in is closed
} // <-- start a new iteration

只需一次迭代, System.in就會關閉。 當然,您在下一次迭代中創建了一個新的Scanner ,但System.in 仍然關閉 ,這就是您在這種情況下獲得異常的原因。

你的第三個例子:

try(Scanner scanner = new Scanner(System.in)){
    while (!input.equals("q")) {
        ...
    } // <-- start a new iteration, while still in the same try block
} // <-- only after the while, your resources are closed

在這里你循環你的while仍然在里面 try 因此,沒有資源得到關閉,直到你離開whiletry 這意味着,一個Scanner保持完整,並使用一個System.in 這允許您在完成循環之前繼續從控制台讀取。

試試這個:

   String input = "";
   try (Scanner scanner = new Scanner(System.in)) {
       while (!input.equals("q")) {
           System.out.print("Input: ");
           input = scanner.nextLine();
           System.out.println("Input was: " + input);
       }
   }

您可以在try-with-resources中使用實現CloseableAutoCloseable每個類,當代碼到達try調用的末尾時,它在我們的示例中調用Scanner類的close()函數。

我運行一些測試並將catch塊添加到您的代碼中。這是代碼

public static void main(String[] args) {
    String input = "";
    while (!input.equals("q")) {
        try(Scanner scanner = new Scanner(System.in)){
            System.out.print("Input: ");
            input = scanner.nextLine();
            System.out.println("Input was: " + input);
        }
        catch (Exception e) {
            e.printStackTrace();
        }            
    }
}

當添加catch塊時,有2種結果1,只輸入q,按預期工作2,輸入任何其他String,異常

Input: java.util.NoSuchElementException: No line found
at java.util.Scanner.nextLine(Scanner.java:1585)
at rews.pub.Test.main(Test.java:11)

當添加catch塊時,我們將看到程序不會因為while循環而停止

這是另一個更容易的測試

public class Test {
public static void main(String[] args) {
    String input = "";
    Scanner scanner = new Scanner(System.in);
    System.out.println("inout--1---");
    input = scanner.nextLine();
    scanner.close();

    Scanner scanner2 = new Scanner(System.in);
    System.out.println("inout--2---");
    input = scanner2.nextLine();
    scanner2.close();

}

}

它也是同樣的例外

inout--1---
11
inout--2---
Exception in thread "main" java.util.NoSuchElementException: No line  found
at java.util.Scanner.nextLine(Scanner.java:1585)
at rews.pub.Test.main(Test.java:15)

這是我的意見。 在第一次運行結束時,try()塊將關閉塊中的資源,意味着我們關閉system.in system.in是inputSteam的對象,而system.in是final和static,我們不能像'new Scanner(System.in)'一樣打開它

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM