繁体   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