一、核心一句话区别
try‑catch‑finally:手动关流 ,很容易忘关、漏关、异常嵌套导致关不掉,容易文件占用、内存泄漏。try‑with‑resources:自动关流 (实现AutoCloseable接口),无论正常/异常/return,100% 关闭资源,Java7+ 推荐标准写法。
二、逐点详细对比(结合你文件流场景)
1. 关闭方式
try‑catch‑finally(传统)
java
InputStream in = null;
try {
in = Files.newInputStream(filePath);
// 读写文件
} catch (Exception e) {
} finally {
// 必须手动关闭,还要判空、try‑catch
if(in != null) {
try { in.close(); } catch (IOException e) {}
}
}
问题:
- 代码啰嗦
- finally 内 close 也可能抛异常,导致后面流关不掉
- 多个流嵌套,关闭顺序容易错
- 漏写 close → 文件被占用、删不掉(你之前遇到的问题)
try‑with‑resources(新式)
java
try (InputStream in = Files.newInputStream(filePath)) {
// 读写
} catch (Exception e) {
}
- 不用手动
close() - 无论正常结束、异常、return、break,JVM 自动调用 close()
- 多个流用
;分隔,自动依次关闭
2. 异常屏蔽(重点!)
try‑catch‑finally
业务代码抛异常 + finally 里 close 又抛异常
→ close 异常会吞掉业务异常,排查问题极难。
try‑with‑resources
- 业务异常为主异常
- close 异常作为抑制异常(suppressed),不会吞主异常
- 日志能看到完整堆栈,便于排查
3. 多流关闭(你 ZIP 场景最典型)
try‑catch‑finally(地狱)
java
InputStream in = null;
FileOutputStream fos = null;
ZipOutputStream zos = null;
try {
in = ...; fos=...; zos=...;
} catch (Exception e) {}
finally {
if(zos!=null) try{zos.close();}catch(Exception e){}
if(fos!=null) try{fos.close();}catch(Exception e){}
if(in!=null) try{in.close();}catch(Exception e){}
}
关闭顺序、判空、嵌套 try‑catch,极易写错。
try‑with‑resources(一行搞定)
java
try (InputStream in = ...;
FileOutputStream fos = ...;
ZipOutputStream zos = ...) {
}
自动按反向顺序关闭:zos → fos → in,完全正确。
三、结合你这段 ZIP 代码的结论
你现在用的 try‑with‑resources:
✅ 无论压缩/读取中途抛异常,所有流自动关闭
✅ 不会出现文件被占用、删不掉
✅ 代码简洁、安全、无泄漏
如果改成 try‑catch‑finally:
大概率会因为漏关/关闭异常,导致文件占用,删除失败。
四、使用条件(记住)
只有实现了 AutoCloseable 接口的类才能用:
- Java IO 流:
InputStream、OutputStream、ZipOutputStream等全部实现了 - Hutool/自定义工具类只要实现该接口,也能用
五、最简记忆口诀
- 传统:手动关,容易漏,异常吞,坑多
- 新式:自动关,零泄漏,顺序对,安全稳
- 文件、网络、数据库连接一律用 try‑with‑resources