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不行呢?
试试这个:
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
的 class,当代码到达 try 调用的末尾时,它会调用 close()
函数 Scanner
class 在我们的例子中。
为我的评论添加更多细节
一个try-with
块定义如下:
try(...) {
...
}
其中括号中的参数需要是java.lang.AutoCloseable
. An example is the class java.io.InputStream
的实例,这也是System.in
的class。
A 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
。因此,在您离开 while
和 try
之前,不会关闭任何资源。这意味着 Scanner
和 System.in
保持不变。这允许您继续从控制台读取,直到您完成循环。
我 运行 一些测试并将 catch 块添加到您的 code.here 的代码中
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块时,有两种结果
1,仅输入 q,按预期工作
2,输入任何其他字符串,异常
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静态的,不能像'new Scanner(System.in)'
一样再次打开
我有两个版本的 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不行呢?
试试这个:
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
的 class,当代码到达 try 调用的末尾时,它会调用 close()
函数 Scanner
class 在我们的例子中。
为我的评论添加更多细节
一个try-with
块定义如下:
try(...) {
...
}
其中括号中的参数需要是java.lang.AutoCloseable
. An example is the class java.io.InputStream
的实例,这也是System.in
的class。
A 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
。因此,在您离开 while
和 try
之前,不会关闭任何资源。这意味着 Scanner
和 System.in
保持不变。这允许您继续从控制台读取,直到您完成循环。
我 运行 一些测试并将 catch 块添加到您的 code.here 的代码中
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块时,有两种结果 1,仅输入 q,按预期工作 2,输入任何其他字符串,异常
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静态的,不能像'new Scanner(System.in)'
一样再次打开