安全关闭流
try-with-resources
安全关闭流 是 CoddyKit 上的免费 Java Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Java Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Java Academy 课程共包含 4 节课。
为什么要关闭流
像 BufferedReader 这样的流会占用系统资源 — 文件句柄、内存缓冲区和连接。如果始终不关闭它们,这些资源就可能发生泄漏。
关闭流会释放其占用的资源,并刷新所有待处理的数据。本课将展示如何安全地完成这一操作。
close 方法
每个读取器都有一个 close() 方法。调用它会释放资源。
对于包装 System.in 的 BufferedReader,关闭它也会关闭它所包装的底层流。
BufferedReader br =
new BufferedReader(new InputStreamReader(System.in));
// ... use br ...
br.close();旧的高风险方式
您可以手动调用 close(),但如果该行执行前发生错误,close() 就会被跳过,从而导致资源泄漏。
将 close() 放在 finally 代码块中会有所帮助,但代码冗长,也很容易出错。
BufferedReader br = null;
try {
br = new BufferedReader(
new InputStreamReader(System.in));
// ... use br ...
} finally {
if (br != null) br.close();
}资源自动管理
Java 有一种更简洁的解决方案:资源自动管理。您可以在 try 后面的括号中声明流,代码块结束时 Java 会自动关闭它 — 即使发生错误也是如此。
无需使用 finally,也无需手动调用 close()。这是目前推荐的最佳做法。
try (BufferedReader br =
new BufferedReader(new InputStreamReader(System.in))) {
String line = br.readLine();
System.out.println(line);
}工作原理
在 try (...) 括号中声明的任何资源都必须实现 AutoCloseable。BufferedReader 实现了它,因此 Java 会替您调用它的 close()。
代码块结束后就会执行关闭操作,无论代码块是正常结束,还是因异常结束。
完整示例
下面是一个使用资源自动管理读取一行内容的完整程序。读取器会在代码块末尾自动关闭。
它从 System.in 读取内容,因此会等待输入,无法在此处自动运行。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
try (BufferedReader br = new BufferedReader(
new InputStreamReader(System.in))) {
String name = br.readLine();
System.out.println("Hi " + name);
}
}
}使用 StringReader 运行
为了证明资源自动管理无需键盘输入即可工作,这里使用 StringReader 读取内容。该示例可以完整运行。
代码块结束后,读取器会自动关闭 — 您无需编写任何 close() 调用。
import java.io.BufferedReader;
import java.io.StringReader;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
try (BufferedReader br =
new BufferedReader(new StringReader("done"))) {
System.out.println(br.readLine());
}
}
}多个资源
您可以在一个 try 中声明多个资源,并用分号分隔。Java 会按照声明顺序的相反顺序关闭它们。
当您将多个流包装在一起时,这种方式非常方便。
try (InputStreamReader isr =
new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr)) {
System.out.println(br.readLine());
}捕获 IOException
读取操作可能抛出 IOException。您可以在资源自动管理代码块中添加 catch 来处理它,而不必声明 throws。
资源仍会在执行 catch 之前自动关闭。
try (BufferedReader br = new BufferedReader(
new InputStreamReader(System.in))) {
System.out.println(br.readLine());
} catch (IOException e) {
System.out.println("Read failed");
}应该关闭 System.in 吗
需要注意的是:关闭基于 System.in 的读取器也会关闭 System.in 本身,而且您无法重新打开它。
对于简短的程序,这样做没有问题。但如果之后仍需要控制台输入,请不要关闭这个特定的读取器。请了解您的流包装了什么。
最佳实践
要安全地处理流:
- 优先使用资源自动管理,而不是手动调用
close()。 - 即使发生错误,它也会自动关闭资源。
- 请记住,关闭
System.in读取器会关闭标准输入。
妥善处理资源可以防止泄漏和错误。
快速检查
请思考资源自动管理的主要优点。
总结
您了解了为什么必须关闭流、手动调用 finally 的高风险方式,以及可以自动关闭 AutoCloseable 资源的简洁资源自动管理模式。
现在,您可以从头到尾安全地使用 BufferedReader 读取输入。
常见问题解答
「安全关闭流」课时是免费的吗?
是的 — 「安全关闭流」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Java Academy 课程的其余内容,请升级到 CoddyKit PRO。 Java Academy 课程共包含 4 节课。
「安全关闭流」这节课中我会学到什么?
try-with-resources 你通过在浏览器中直接运行的动手代码来练习 Java Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Java Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Java Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「安全关闭流」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Java Academy 课中编写并运行代码吗?
能。每节 Java Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。