InputStream 必须用 try/catch 捕捉?

2022-07-18 14:36:53 +08:00
 Richard14

根据廖雪峰教学文章中提供的代码,

https://www.liaoxuefeng.com/wiki/1252599548343744/1298069163343905

我在使用 FileInputStrem 打开和关闭文件时都必须添加 trycatch

InputStream input = new FileInputStream("src/readme.txt");
input.close()

否则编译器就会提示 java: 未报告的异常错误 java.io.FileNotFoundException; 必须对其进行捕获或声明以便抛出。这导致一个读取文件的逻辑要三次 trycatch ,非常不优雅。

根据其后文的描述可以采用

try (InputStream input = new FileInputStream("src/readme.txt")) {
}

的方式让编译器自动补全 finally 后的 close ,但是我尝试其代码编译器仍提示必须捕捉 Exception 。

请问这是由于 jdk 版本不同引发的从错误吗? javaer 正常打开和关闭文件的姿势是什么样的

3147 次点击
所在节点    Java
21 条回复
dcsuibian
2022-07-18 14:38:21 +08:00
try{

}catch(Exception e){
throw new RuntimeException(e);
}
seanzxx
2022-07-18 14:41:47 +08:00
正常的呀,Java 有一种叫做 checked exception 的东西,就是一定要处理,否则编译不过
你这个打开读到的语句至少有两种异常要处理,FileNotFoundException, IOException
857681664
2022-07-18 14:44:15 +08:00
1. java 的几个关于 ioexception 的都是 checkedException, 需要显示捕获或者在调用方法上声明 throws, 如果觉得分开 3 次 try catch 繁琐,可以把几个 io 操作放一个大的 try catch 里
2. try-with-resource 语法是 jdk1.7 之后才有的,你可以看一下自己的 jdk 版本是否符合要求,如果是用 IDEA, 看看是否设置了 language level 是不是 1.7+
chendy
2022-07-18 14:46:44 +08:00
try with resources 是编译器自动补全 finally 后的 close ,并没有补 catch ,所以还是需要自己 catch 的
Zerek
2022-07-18 14:47:54 +08:00
有个东西叫做 lombok

https://blog.51cto.com/attilax2/3655310
//Lombok ?
对冗长的 try/catch/finally 的一次包
清单 6. 使用 @Cleanup 注释
public static void main(String[] args) throws IOException {
@Cleanup InputStream in = new FileInputStream(args[0]);
@Cleanup OutputStream out = new FileOutputStream(args[1]);
//write file code goes here
}
Jwyt
2022-07-18 14:48:05 +08:00
三次 trycatch 是怎么来的?
像这种文本文件我都是 Files.readString()一把梭

try (InputStream input = new FileInputStream("src/readme.txt")) {
}
这种写法是 try-with-resource, 你用这种就不用手动执行 close 操作了,也只是一次 trycatch 阿,哪来的三次?
dcsuibian
2022-07-18 14:52:16 +08:00
@dcsuibian 转成 RuntimeException 然后抛,或者打印一下日志再抛。留给最上层处理。

Java 的检查型异常是个没啥用的东西,其它语言都没有采用这种机制( C++:???)。
最不实用的地方在于:就算你捕获到了这个异常,你也不知道怎么处理。

网络、文件很容易出问题,但出问题了咋整,再试几次?试过几次还是不行呢?万一在 close 的时候出现异常呢?
看看那些 ORM 框架、或者文件操作工具库,很明显底层一定会有 IO 操作,但他们就不会在方法上加一堆 throws 。
XXWHCA
2022-07-18 16:08:10 +08:00
Java 的 io 操作就按着模版代码写吧,没有什么好办法,流读写,关闭输入输出流,三次 try-catch 是最基本的,最多使用 StreamUtil.close(stream)。
大部分流都是需要 close 的,只有一部分内存流可以忽略,例如 ByteArrayXxxStream ,StringReader 等。
像文件读写复制什么的,只能靠工具方法来减少模版代码的编写
matepi
2022-07-18 16:41:02 +08:00
@dcsuibian 要么抓明确的 IOException ,要抓上层就抓 Throwable ,抓 Exception 总感觉会漏

可以看一下这里,为什么要抓 Throwable
https://www.v2ex.com/t/638609
dcsuibian
2022-07-18 19:38:21 +08:00
@matepi 随手写的,平时用的就是具体异常(反正 try/catch 是 IDE 写的)。

Exception 比起 Throwable 来说,漏掉的就是 Error 。但 Error 本身就是那些严重到程序员无法处理的错误了。
[When to catch java.lang.Error?]( https://stackoverflow.com/questions/352780/when-to-catch-java-lang-error)

我一般将 Error 看作是系统崩坏。
比如某个接口抛出了 Exception ,我可能还 catch 一下,打个日志,返回个错误信息,至少其它接口还能用。
而如果捕获到一个 Error ,我认为 jvm 就不可靠了,直接挂了吧。
aguesuka
2022-07-18 19:41:54 +08:00
@dcsuibian 可以用 uncheckedioexception, 语义比 RuntimeException 好
zed1018
2022-07-18 20:51:34 +08:00
@matepi 在我组,我是明令禁止非必要抓 throwable 的,如果不能枚举足够的异常,那就是设计上根本就有问题。瞎抓不可取,该 crash 的一定要 crash 减少影响面
yeqizhang
2022-07-18 21:26:35 +08:00
v 站大佬多呀,提的问题也都很好,今天又学习到了
ychost
2022-07-18 22:27:56 +08:00
@SneakThrows 用这个注解
blankmiss
2022-07-18 22:56:50 +08:00
@ychost 这个注解好像是为了骗过编译器来着
ErnestSu
2022-07-19 09:28:47 +08:00
@zed1018
在我组,我是明令禁止非必要抓 throwable 的,如果不能枚举足够的异常,那就是设计上根本就有问题。瞎抓不可取,该 crash 的一定要 crash 减少影响面
---------------------
调用定制系统的 api ,不一定所有版本有这个实现,所有定制系统的 api ,我都会 catch Throwable
nothingistrue
2022-07-19 09:29:27 +08:00
try (InputStream input = new FileInputStream("src/readme.txt")) {

}catch (IOException e){

}

这才是正确的用法,因为 try-with-resources 只是自动调用 close (以及将 finally 当中抛出的异常转移到 try 当中抛出), 但不隐藏异常,对于 IOException 这种受检异常,你必须自己处理。
nothingistrue
2022-07-19 09:32:01 +08:00
@zed1018
@ErnestSu
重点不是是否 catch ,是 catch 之后不能即不处理又不 throw 。
shily
2022-07-19 18:53:08 +08:00
kotlin 解君愁
night98
2022-07-19 21:05:10 +08:00
try with resource 的功能是自动关闭流,和异常捕获没有半毛钱关系,在 Java 中受检异常是必须要被处理的,嫌麻烦直接用 hutool 的文件工具类

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/867006

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX