try-with-resources 无需判空,因资源在 try() 内声明并初始化,编译器确保成功创建则必关闭,失败则变量未赋值;多资源按逆序自动关闭,且要求实现 autocloseable。

try-with-resources 直接绕开了传统 IO 中那一堆 if (resource != null) 和嵌套 try-catch 的判空逻辑,核心在于把“资源是否创建成功”和“是否需要关闭”这两件事交给编译器统一判断——只要资源在 try() 括号里声明并初始化成功,就一定会被关闭;如果初始化失败(比如构造函数抛异常),那变量根本不会被赋值,自然也无需关闭。
为什么不用再判空了
传统写法中反复出现 if (input != null) 是因为资源变量声明在 try 外部,可能为 null。而 try-with-resources 要求资源必须在 try() 内完成声明和初始化,JVM 保证:
- 如果 new FileInputStream("a.txt") 成功,input 变量一定非 null,close() 必然执行
- 如果 new FileInputStream("a.txt") 抛出 FileNotFoundException,input 根本没被创建,也就不存在关闭问题
- 编译器生成的底层代码已内置非空检查和异常捕获,你完全不用写
一个对比:读文件的两种写法
传统方式(含冗余判空):
FileInputStream fis = null;
try {
fis = new FileInputStream("data.txt");
// 读取逻辑
} catch (IOException e) {
throw e;
} finally {
if (fis != null) { // 判空必不可少
try { fis.close(); } catch (IOException ignored) {}
}
}
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
try-with-resources(零判空):
try (FileInputStream fis = new FileInputStream("data.txt")) {
// 读取逻辑,fis 一定可用
} catch (IOException e) {
throw e;
}
// ← 这里 fis 已自动关闭,无 null 风险,无额外 try-catch
多个资源时依然不需手动干预
当组合使用装饰流时,比如 BufferedReader 包裹 FileReader,声明顺序决定了关闭顺序,也彻底规避了手动管理依赖关系的麻烦:
- try (FileReader fr = new FileReader("a.txt"); BufferedReader br = new BufferedReader(fr)) { ... }
- br 先关闭(触发 flush 和内部清理),fr 后关闭——这个逆序由 JVM 自动保障
- 你不需要、也不应该去写 if (br != null) 或 if (fr != null)
注意边界:资源必须是 AutoCloseable 且现场初始化
以下写法会失效,仍可能引发空指针或不关闭:
- ❌ 把流提前声明:FileInputStream fis; try (fis = new FileInputStream(...)) → 编译错误,语法不合法
- ❌ 使用未实现 AutoCloseable 的类(如 Java 19 前的 Scanner)→ 编译报错
- ✅ 自定义类只需 implements AutoCloseable,并提供幂等的 close() 方法即可接入
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










