try-with-resource从入门到使用
2020/2/3 23:44:49
本文主要是介绍try-with-resource从入门到使用,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
try-with-resource是从java7开始提供的新特性。方便了我们资源的代码编写。下面展示一下代码模板的对比
没有try-with-resource
try{ 资源打开 业务逻辑 }catch(Exception e){ 异常处理 }finally{ 资源关闭 }
try-with-resource的
try(资源打开){ 业务逻辑 }catch(Exception e){ 异常处理 }
案例分析
看了上面的模板,我们的一个直观感觉是省去了finally,并且把资源放在了try后面的括号中。下面展示一段真实的代码。
public static void main(String[] args) { try ( InputStream fileInputStream = Files.newInputStream(Paths.get("/Users/xie/delete/test.txt")); OutputStream outputStream = Files.newOutputStream(Paths.get("/Users/xie/delete/test2.txt")); ) { byte[] bytes = new byte[1024]; int len; while ((len = fileInputStream.read(bytes)) > 0) { outputStream.write(bytes, 0, len); } } catch (IOException e) { e.printStackTrace(); } }
注:上面的代码只是演示了一个文件拷贝的方法,如果我们自己写代码请选择1.7提供的Files.copy。
try-with-resource做了什么
我们通过反编译工具来做一下对比
public static void main(String[] args) { try { InputStream fileInputStream = Files.newInputStream(Paths.get("/Users/xie/delete/test.txt")); Throwable var2 = null; try { OutputStream outputStream = Files.newOutputStream(Paths.get("/Users/xie/delete/test2.txt")); Throwable var4 = null; try { byte[] bytes = new byte[1024]; int len; while((len = fileInputStream.read(bytes)) > 0) { outputStream.write(bytes, 0, len); } } catch (Throwable var30) { var4 = var30; throw var30; } finally { if (outputStream != null) { if (var4 != null) { try { outputStream.close(); } catch (Throwable var29) { var4.addSuppressed(var29); } } else { outputStream.close(); } } } } catch (Throwable var32) { var2 = var32; throw var32; } finally { if (fileInputStream != null) { if (var2 != null) { try { fileInputStream.close(); } catch (Throwable var28) { var2.addSuppressed(var28); } } else { fileInputStream.close(); } } } } catch (IOException var34) { var34.printStackTrace(); } }
基本从字节码反编译过来,我们可以看到他是按照我们熟悉的方式编写的代码。所以try-with-resource是语法糖。
这里大家不熟悉的可能就是一场处理里面有addSuppressed的调用。这是一个异常新加的方法,抑制异常。其实这种场景很常见,一个方法里执行出了多个异常,应该报哪个呢,虽然都能表示这个方法调用的失败。以前的做法就是自己catch然后做一些逻辑操作,最后抛出一个。有了这个方法就能实现以前的逻辑,逻辑中也可以取出被抑制的异常信息。
使用的注意事项
- 第三方库的资源使用需要了解,他的资源是否实现了Closeable。
jdk的资源是都实现了这个接口。
class OutputStream implements Closeable, Flushable {
只有实现了Closeable的才可以和try-with-resource搭配使用。
- 需要了解每个资源的关闭细节
这里需要列举两个情况。
- socket的流的关闭会导致socket关闭。
下面以inputstream为例。SocketInputStream集成FileInputStream,所以也实现了Closeable。
class SocketInputStream extends FileInputStream
但是他的close方法做的事情有点多,会检测socket是否关闭。
public void close() throws IOException { if (closing) return; closing = true; if (socket != null) { if (!socket.isClosed()) socket.close(); } else impl.close(); closing = false; }
- 输出流关闭没有flush
这是我调用别人写的库的时候遇到的问题,一直发现文件超过一定大小就会传输丢失。习惯了很多库都是close会顺带帮你做flush。
上面的这些情况,本身就是使用流该注意的地方。
- 资源声明顺序
通过上面的例子,其实资源也是和我们自己写代码的思路一致,先声明的后关闭。
9版本的改进
java9之前的try-with-resource都是必须做一次赋值的。
public static void read(InputStream fileInputStream) { try (InputStream fileInputStreamTmp = fileInputStream) { byte[] bytes = new byte[1024]; int len; while ((len = fileInputStreamTmp.read(bytes)) > 0) { } } catch (IOException e) { e.printStackTrace(); } }
这个问题也挺明显的,我都开始名字上加Tmp来标识了。
9之后就彻底不用这么做了
public static void read(InputStream fileInputStream) { try (fileInputStream) { byte[] bytes = new byte[1024]; int len; while ((len = fileInputStream.read(bytes)) > 0) { } } catch (IOException e) { e.printStackTrace(); } }
这篇关于try-with-resource从入门到使用的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-06-26终极指南:Scrum中如何设置需求优先级
- 2024-06-26AI大模型企业应用实战(25)-为Langchain Agent添加记忆功能
- 2024-06-26小白家庭 nas 搭建方案-icode9专业技术文章分享
- 2024-06-23AI大模型企业应用实战(14)-langchain的Embedding
- 2024-06-23AI大模型企业应用实战(15)-langchain核心组件
- 2024-06-23AI大模型企业应用实战(16)-langchain核心组件
- 2024-06-23AI 大模型企业应用实战(06)-初识LangChain
- 2024-06-19EntBot.ai: AI Website Chatbot for Product Guides and Development Doc
- 2024-06-17zero-shot-learning-definition-examples-comparison
- 2024-06-06Package Easy(基于 NSIS 的打包exe安装包工具)使用方法-icode9专业技术文章分享