1. 引言
使用Java的Scanner
类读取System.in
输入时,IDE常会提示资源泄漏警告。**若未显式关闭Scanner
*,可能会看到类似“Resource leak: 'scanner' is never closed*”的警告。但关闭与System.in
绑定的Scanner
需谨慎处理,否则可能引发意外问题。
本文将探讨关闭Scanner
的重要性及正确操作方式。
2. 理解警告机制
Java中,文件、网络连接、输入流等资源使用后应关闭以释放系统内存。Scanner
类实现了Closeable
接口,用于读取原始值和字符串(包括文件和System.in
),其持有的资源需在不再使用时释放。
主流IDE(如Eclipse、VS Code)在未正确关闭Scanner
时会显示警告:
3. 使用close()
方法关闭Scanner
通过close()
方法可释放Scanner
占用的系统资源,尤其当读取文件或System.in
时。最佳实践是在finally
块中关闭,确保异常发生时资源仍能正确释放:
@Test
void givenUserName_whenGetGreetingMessage_thenReturnsWelcomeMessage() {
String input = "Anees\n";
ByteArrayInputStream inputStream = new ByteArrayInputStream(input.getBytes());
Scanner scanner = new Scanner(inputStream);
ScannerClose example = new ScannerClose();
String result = example.getGreetingMessage(scanner);
assertEquals("Hi, Anees Welcome to Baeldung", result);
scanner.close();
}
⚠️ 踩坑预警:关闭与System.in
绑定的Scanner
会引发问题。System.in
代表标准输入流(通常是键盘),关闭后程序将无法读取用户输入,且在同一程序中无法重新打开。
若创建多个System.in
的Scanner
实例,关闭任一实例都会导致整个程序的输入流关闭。再次读取输入时将抛出异常:
Scanner scanner = new Scanner(System.in);
System.out.print("Enter your name: ");
String name = scanner.nextLine();
System.out.println("Hi, " + name + " Welcome to Baeldung!");
scanner.close();
System.out.print("Enter your age: ");
int age = scanner.nextInt();
System.out.println("Your age is: " + age);
执行结果:
Enter your name: Anees
Hi, Anees Welcome to Baeldung!
Enter your age: Exception in thread "main" java.lang.IllegalStateException: Scanner closed
at java.base/java.util.Scanner.ensureOpen(Scanner.java:1150)
at java.base/java.util.Scanner.next(Scanner.java:1573)
at java.base/java.util.Scanner.nextInt(Scanner.java:2258)
at java.base/java.util.Scanner.nextInt(Scanner.java:2212)
✅ 正确实践:
- 对
System.in
使用单一Scanner
实例 - 避免关闭,或仅在不再需要输入时关闭
4. 使用try-with-resources
关闭Scanner
通过try-with-resources可在代码块结束时自动关闭Scanner
,即使发生异常也能确保资源释放。无需finally
块,降低资源泄漏风险:
@Test
void givenUserName_whenGetGreetingMessage_thenReturnsWelcomeMessage() {
String input = "Anees\n";
ByteArrayInputStream inputStream = new ByteArrayInputStream(input.getBytes());
String result;
try (Scanner scanner = new Scanner(inputStream)) {
ScannerTryWithResources example = new ScannerTryWithResources();
result = example.getGreetingMessage(scanner);
}
assertEquals("Hi, Anees Welcome to Baeldung", result);
}
try
块执行完毕后,Java自动关闭Scanner
实例,使代码更简洁可靠。**强烈推荐使用try-with-resources
**,它确保资源清理的可靠性。
5. 总结
本文探讨了关闭Scanner
的重要性及正确方法。良好的资源管理可防止泄漏,保障程序稳定运行。
✅ 关键要点:
- 读取文件时必须关闭
Scanner
- 处理
System.in
需格外谨慎:使用单一实例,仅在不再需要输入时关闭 try-with-resources
是资源管理的最佳实践,确保自动关闭且代码更健壮