Java使用带有try-with-resources的扫描程序

时间:2017-12-01 07:39:52

标签: java try-catch 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还不行?

3 个答案:

答案 0 :(得分:3)

在我的评论中添加更多细节

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后,你再也无法从控制台获得任何输入(至少没有额外的工作,我认为......)。

具体地说,在你的第二个例子中:

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就是 $date_query[] = array( 'after' => get_query_var( 'timestart'), 'before' => get_query_var('timeend') ); $date_query['relation'] = 'AND'; $date_query['inclusive'] = true; 。这允许您在完成循环之前继续从控制台读取。

答案 1 :(得分:0)

试试这个:

   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调用的末尾时,它调用close()函数Scanner我们的例子中有1}}类。

答案 2 :(得分:0)

我运行一些测试并将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,我们不能像新的Scanner(System.in)&#39;

一样再次打开它。