[英]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
。 因此,沒有資源得到關閉,直到你離開while
與try
。 這意味着,一個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中使用實現Closeable
或AutoCloseable
每個類,當代碼到達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.