[英]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.