根据廖雪峰教学文章中提供的代码,
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 正常打开和关闭文件的姿势是什么样的
1
dcsuibian 2022-07-18 14:38:21 +08:00
try{
}catch(Exception e){ throw new RuntimeException(e); } |
2
seanzxx 2022-07-18 14:41:47 +08:00
正常的呀,Java 有一种叫做 checked exception 的东西,就是一定要处理,否则编译不过
你这个打开读到的语句至少有两种异常要处理,FileNotFoundException, IOException |
3
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+ |
4
chendy 2022-07-18 14:46:44 +08:00
try with resources 是编译器自动补全 finally 后的 close ,并没有补 catch ,所以还是需要自己 catch 的
|
5
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 } |
6
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 阿,哪来的三次? |
7
dcsuibian 2022-07-18 14:52:16 +08:00 1
@dcsuibian 转成 RuntimeException 然后抛,或者打印一下日志再抛。留给最上层处理。
Java 的检查型异常是个没啥用的东西,其它语言都没有采用这种机制( C++:???)。 最不实用的地方在于:就算你捕获到了这个异常,你也不知道怎么处理。 网络、文件很容易出问题,但出问题了咋整,再试几次?试过几次还是不行呢?万一在 close 的时候出现异常呢? 看看那些 ORM 框架、或者文件操作工具库,很明显底层一定会有 IO 操作,但他们就不会在方法上加一堆 throws 。 |
8
XXWHCA 2022-07-18 16:08:10 +08:00
Java 的 io 操作就按着模版代码写吧,没有什么好办法,流读写,关闭输入输出流,三次 try-catch 是最基本的,最多使用 StreamUtil.close(stream)。
大部分流都是需要 close 的,只有一部分内存流可以忽略,例如 ByteArrayXxxStream ,StringReader 等。 像文件读写复制什么的,只能靠工具方法来减少模版代码的编写 |
9
matepi 2022-07-18 16:41:02 +08:00
@dcsuibian 要么抓明确的 IOException ,要抓上层就抓 Throwable ,抓 Exception 总感觉会漏
可以看一下这里,为什么要抓 Throwable https://www.v2ex.com/t/638609 |
10
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 就不可靠了,直接挂了吧。 |
11
aguesuka 2022-07-18 19:41:54 +08:00 1
@dcsuibian 可以用 uncheckedioexception, 语义比 RuntimeException 好
|
12
zed1018 2022-07-18 20:51:34 +08:00
@matepi 在我组,我是明令禁止非必要抓 throwable 的,如果不能枚举足够的异常,那就是设计上根本就有问题。瞎抓不可取,该 crash 的一定要 crash 减少影响面
|
13
yeqizhang 2022-07-18 21:26:35 +08:00 via Android
v 站大佬多呀,提的问题也都很好,今天又学习到了
|
14
ychost 2022-07-18 22:27:56 +08:00
@SneakThrows 用这个注解
|
16
ErnestSu 2022-07-19 09:28:47 +08:00
@zed1018
在我组,我是明令禁止非必要抓 throwable 的,如果不能枚举足够的异常,那就是设计上根本就有问题。瞎抓不可取,该 crash 的一定要 crash 减少影响面 --------------------- 调用定制系统的 api ,不一定所有版本有这个实现,所有定制系统的 api ,我都会 catch Throwable |
17
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 这种受检异常,你必须自己处理。 |
18
nothingistrue 2022-07-19 09:32:01 +08:00
|
19
shily 2022-07-19 18:53:08 +08:00 via iPhone
kotlin 解君愁
|
20
night98 2022-07-19 21:05:10 +08:00
try with resource 的功能是自动关闭流,和异常捕获没有半毛钱关系,在 Java 中受检异常是必须要被处理的,嫌麻烦直接用 hutool 的文件工具类
|