java 9 允许在 try-with-resources 中直接使用已声明的 final 或 effectively final 变量,避免重复声明;effectively final 指未显式声明 final 但从未被重新赋值的变量;多个资源可用分号并列,按逆序自动关闭。

Java 9 中可以直接在 try-with-resources 语句里使用已声明的 final 或 effectively final 变量,不用再重复声明新变量。这解决了 Java 8 及之前版本中“明明变量已经存在,却还要在 try() 里再造一遍”的冗余问题。
什么是 effectively final?
一个变量没有显式加 final 关键字,但自声明后从未被重新赋值,编译器就视其为 effectively final。Java 9 允许这类变量直接用于 try-with-resources —— 不强制写 final,但必须保证“不改值”。
- ✅ 合法:
BufferedReader br = new BufferedReader(...);后没再给br赋新值 → 可直接try(br) - ❌ 非法:
br = new BufferedReader(...);出现在 try 前 → 不再是 effectively final → 编译失败
怎么写才真正避免重复定义?
对比 Java 8 和 Java 9 的写法,关键在于“是否多写一次变量声明”:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- Java 8 必须这样(冗余):
InputStream is = Files.newInputStream(path);<br>try (InputStream autoCloseIs = is) { /* 使用 autoCloseIs */ } - Java 9 直接这样(简洁):
InputStream is = Files.newInputStream(path);<br>try (is) { /* 直接用 is */ }
变量名、类型、初始化逻辑都只出现一次,作用域更清晰,调试时堆栈也更干净。
多个资源一起用也没问题
Java 9 支持在同一个 try() 中并列引用多个已声明的 effectively final 资源,用分号隔开:
BufferedReader reader = ...;<br>PrintWriter writer = ...;<br>try (reader; writer) { /* 读写操作 */ }- 两个资源都会按逆序自动关闭(writer 先关,reader 后关),语义和 Java 7/8 完全一致
实际开发中的常见注意点
虽然语法更自由,但几个细节容易踩坑:
- 资源变量必须在 try 语句前完成初始化,不能是 null(否则运行时报 NullPointerException)
- 如果资源创建过程可能抛异常,建议把初始化放在 try 外独立处理,或用 Optional/try-catch 包裹,避免影响 try-with-resources 主流程
- lambda 表达式里捕获的局部变量默认就是 effectively final,所以配合 try-with-resources 写回调逻辑也很自然
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










