通过前篇的《Java文件IO流的操作总结》,我们知道了基本输入输出流的使用方式,但是每次都需要在finally处关闭流资源,这样操作起来既啰嗦又麻烦,有没有更简洁的方式呢?本篇就来讲解jdk1.7引入的try with resources语法糖式写法。

什么是语法糖

1.之所以称之为语法糖,给人的感觉就是很甜,很甜。 
2.在相同功能下,语法糖的写法会让代码更加简洁流畅,代码更加语义自然。
3.通过编译器在编译期间以特定的字节码或者特定的方式对这些语法做一些处理
4.语法糖虽然不会提供实质性的功能改进,但是它们或能提高性能、或能提升语法的严谨性、或能减少编码出错的机会。

使用try with resources捕获异常

待读取的文件内容

示例代码

package com.lingyejun.io;

import java.io.*;

/**
* Created by Lingye on 2018/9/28 15:03
*/
public class SyntacticSugarTry { // 调用有finally的case值
public static final int OLD_TRY = 1;
// 调用新式语法糖式的case值
public static final int SUGAR_TRY = 2; /**
* 根据输入参数执行不同方法
*
* @param type
* @return
*/
public InputStream invokeTry(int type) {
InputStream inputStream = null;
switch (type) {
case OLD_TRY:
inputStream = oldTryCatch();
break;
case SUGAR_TRY:
inputStream = newTryCatch();
break;
default:
System.out.println("error type");
}
return inputStream;
} /**
* 采用旧式的finally写法
*
* @return
*/
public InputStream oldTryCatch(){
// 构建文件对象
File inputFile = new File("D:\\input.txt");
// 初始化输入流
InputStream inputStream = null;
try {
// 创建字节输入流
inputStream = new FileInputStream(inputFile);
// 读取到1KB字节数组中
byte[] buffer = new byte[12];
// 读取数据并放到buffer数组中
inputStream.read(buffer);
System.out.println("oldTryCatch读取输出"+new String(buffer));
} catch (Exception e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
// 关闭流过程,也有可能出现异常
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return inputStream;
} /**
* 采用语法糖式写法
*
* @return
*/
public InputStream newTryCatch() {
// 构建文件对象
File inputFile = new File("D:\\input.txt");
// 初始化输入流
InputStream returnStream = null;
// try with resource 语法糖式写法
try (InputStream inputStream = new FileInputStream(inputFile)) {
byte[] buffer = new byte[12];
inputStream.read(buffer);
System.out.println("newTryCatch读取输出"+new String(buffer));
returnStream = inputStream;
} catch (Exception e) {
e.printStackTrace();
}
// 省略了繁琐的finally
return returnStream;
} public static void main(String[] args) {
SyntacticSugarTry sugarTry = new SyntacticSugarTry();
InputStream oldStream = sugarTry.invokeTry(OLD_TRY);
InputStream sugarStream = sugarTry.invokeTry(SUGAR_TRY);
// 检查流是否正常关闭
try {
// 再次尝试读取,检查是否关闭
oldStream.read();
} catch (IOException e) {
// 已关闭
System.out.println("oldStream 输入流已关闭");
}
try {
// 再次尝试读取,检查是否关闭
sugarStream.read();
} catch (IOException e) {
// 已关闭
System.out.println("sugarStream 输入流已关闭");
}
}
}

查看文件管道的关闭情况

语法糖式写法,执行完毕后自动关闭输入流

查看输出结果

不难看出,语法糖的使用其实就是让我们的写的代码更简单,看起来也更容易理解。

使用原理

语法糖是一种几乎每种语言或多或少都提供过的一些方便程序员开发代码的语法,它只是编译器实现的一些小把戏罢了,编译期间以特定的字节码或者特定的方式对这些语法做一些处理,开发者就可以直接方便地使用了。这些语法糖虽然不会提供实质性的功能改进,但是它们或能提高性能、或能提升语法的严谨性、或能减少编码出错的机会。

使用JD-GUI打开上面类的.class编译文件后会发现编译过后,编译器给我们自动加上了资源流的close关闭动作(81行、95行)。

/* Error */
public InputStream newTryCatch()
{
// Byte code:
// 0: new 49 java/io/File
// 3: dup
// 4: ldc 51
// 6: invokespecial 53 java/io/File:<init> (Ljava/lang/String;)V
// 9: astore_1
// 10: aconst_null
// 11: astore_2
// 12: aconst_null
// 13: astore_3
// 14: aconst_null
// 15: astore 4
// 17: new 55 java/io/FileInputStream
// 20: dup
// 21: aload_1
// 22: invokespecial 57 java/io/FileInputStream:<init> (Ljava/io/File;)V
// 25: astore 5
// 27: bipush 12
// 29: newarray <illegal type>
// 31: astore 6
// 33: aload 5
// 35: aload 6
// 37: invokevirtual 60 java/io/InputStream:read ([B)I
// 40: pop
// 41: getstatic 29 java/lang/System:out Ljava/io/PrintStream;
// 44: new 64 java/lang/StringBuilder
// 47: dup
// 48: ldc 102
// 50: invokespecial 68 java/lang/StringBuilder:<init> (Ljava/lang/String;)V
// 53: new 69 java/lang/String
// 56: dup
// 57: aload 6
// 59: invokespecial 71 java/lang/String:<init> ([B)V
// 62: invokevirtual 74 java/lang/StringBuilder:append (Ljava/lang/String;)Ljava/lang/StringBuilder;
// 65: invokevirtual 78 java/lang/StringBuilder:toString ()Ljava/lang/String;
// 68: invokevirtual 37 java/io/PrintStream:println (Ljava/lang/String;)V
// 71: aload 5
// 73: astore_2
// 74: aload 5
// 76: ifnull +55 -> 131
// 79: aload 5
// 81: invokevirtual 87 java/io/InputStream:close ()V
// 84: goto +47 -> 131
// 87: astore_3
// 88: aload 5
// 90: ifnull +8 -> 98
// 93: aload 5
// 95: invokevirtual 87 java/io/InputStream:close ()V
// 98: aload_3
// 99: athrow
// 100: astore 4
// 102: aload_3
// 103: ifnonnull +9 -> 112
// 106: aload 4
// 108: astore_3
// 109: goto +15 -> 124
// 112: aload_3
// 113: aload 4
// 115: if_acmpeq +9 -> 124
// 118: aload_3
// 119: aload 4
// 121: invokevirtual 104 java/lang/Throwable:addSuppressed (Ljava/lang/Throwable;)V
// 124: aload_3
// 125: athrow
// 126: astore_3
// 127: aload_3
// 128: invokevirtual 82 java/lang/Exception:printStackTrace ()V
// 131: aload_2
// 132: areturn
// Line number table:
// Java source line #75 -> byte code offset #0
// Java source line #77 -> byte code offset #10
// Java source line #79 -> byte code offset #12
// Java source line #80 -> byte code offset #27
// Java source line #81 -> byte code offset #33
// Java source line #82 -> byte code offset #41
// Java source line #83 -> byte code offset #71
// Java source line #84 -> byte code offset #74
// Java source line #85 -> byte code offset #127
// Java source line #88 -> byte code offset #131
// Local variable table:
// start length slot name signature
// 0 133 0 this SyntacticSugarTry
// 9 13 1 inputFile java.io.File
// 11 121 2 returnStream InputStream
// 13 1 3 localObject1 Object
// 87 16 3 localObject2 Object
// 108 17 3 localObject3 Object
// 126 2 3 e Exception
// 15 1 4 localObject4 Object
// 100 20 4 localThrowable Throwable
// 25 69 5 inputStream InputStream
// 31 27 6 buffer byte[]
// Exception table:
// from to target type
// 27 74 87 finally
// 17 100 100 finally
// 12 126 126 java/lang/Exception
}

参考文章:

https://www.cnblogs.com/jiumao/p/7136369.html

https://blog.csdn.net/Merlin2017/article/details/78075206

try with resources简洁的异常捕获机制的更多相关文章

  1. Javascript的异常捕获机制

    這個異常處理機制,之前也只是,但是沒有怎麼用過,用了一次后發現還可以, 和java,python的異常處理機制也很相似 Javascript的异常捕获机制 1.1 基本的try…catch语句 ES3 ...

  2. struts2 进阶--异常捕获机制

    在SpringMvc中有自己的异常处理机制,struts2当然会有此功能,主要是在struts.xml中配置: <bean type="com.opensymphony.xwork2. ...

  3. eggjs异常捕获机制

    1. try catch捕获异步链中的方法 2. ctx.runInBackground(scope)捕获跳出异步链的方法 // 旧代码 class HomeController extends Co ...

  4. C# 异常捕获机制(Try Catch Finally)

    一.C#的异常处理所用到关键字 try 用于检查发生的异常,并帮助发送任何可能的异常. catch 以控制权更大的方式处理错误,可以有多个catch子句. finally 无论是否引发了异常,fina ...

  5. C#中的异常捕获机制(try catch finally)

    (转自:http://blog.csdn.net/zevin/article/details/6901489) 一.C#的异常处理所用到关键字try 用于检查发生的异常,并帮助发送任何可能的异常.ca ...

  6. 异常 Exception 堆栈跟踪 异常捕获 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  7. gRPC全局异常捕获

    gRPC全局异常捕获 引 一般的.net项目比如ASP.NET.控制台程序.Windows服务.桌面程序等都会有framework自带的全局异常捕获机制.ASP.NET的ExceptionFilter ...

  8. C++异常实现机制

    1.C函数的调用和返回 要理解C++异常机制实现之前,首先要了解一个函数的调用和返回机制,这里面就要涉及到ESP和EBP寄存器.我们先看一下函数调用和返回的流程. 下面是按调用约定__stdcall ...

  9. 使用lua实现try-catch异常捕获

    lua原生并没有提供try-catch的语法来捕获异常处理,但是提供了pcall/xpcall等接口,可在保护模式下执行lua函数. 因此,可以通过封装这两个接口,来实现try-catch块的捕获机制 ...

随机推荐

  1. swift学习笔记之—自定义函数的规则说明

    原文出自:www.hangge.com  转载请保留原文链接:http://www.hangge.com/blog/cache/detail_517.html 1,无返回值的函数 func test( ...

  2. GIS-003-在线地图下载及应用

    目前在线地图有谷歌.高德.百度.Bing.soso.天地图.OpenStreet.ArcGIS Online等.在企业应用中,一般需要物理网络隔绝,就有必要下载地图数据之后模拟发布,可以选择下载谷歌影 ...

  3. 【python系列】SyntaxError:Missing parentheses in call to 'print'

    打印python2和python3的区别 如上图所示,我的 PyCharm安装的是python3.6如果使用print 10会出现语法错误,这是python2.x和python3.x的区别所导致的.

  4. LINUX IPTABLES 防火墙配置

     0.iptables(ACL)的匹配原则: 与cisco等一致,从上到下依次匹配. 1.iptables的基本用法:. (1)命令格式 iptables [–ttable] command [mat ...

  5. application/json和application/x-www-form-urlencoded区别

    application/json和application/x-www-form-urlencoded都是表单数据发送时的编码类型. EncType: enctype 属性规定在发送到服务器之前应该如何 ...

  6. SSL安装方法二:Windows Server 2008安装SSL证书(IIS 7.5)

    SSL证书CSR和CA证书唯一的区别就在:申请证书中的通用名称,具体还要看具体的项目这里只做参考.可以参考SSL安装方法一 背景:IIS 7.5 一.收到SSL证书 仔细阅读邮件 按步骤进行: 1)  ...

  7. supervisor安装篇

    服务器环境: [root@kafka60 supervisor-]# uname -a Linux kafka60 -.el6.x86_64 # SMP Tue May :: UTC x86_64 x ...

  8. mysql 修改配置文件性能优化

    vim /etc/my.cnf 原配置文件 [mysqld] datadir=/var/lib/mysql socket=/var/lib/mysql/mysql.sock user=mysql # ...

  9. hibernate基于注解实现映射关系的配置

    关联关系的配置步骤 ①要理清楚管理关系 ②确定管理依赖关系的哪一方 1一对一例如:person 和IdCard ①确定依赖关系:一对一 ②依赖关系由person类管理代码如下: person: @En ...

  10. rk3188 双屏异显分析

      首先是android层: PhoneWindow.java 中加入了GestureDetector成员, 来实现全局滑屏手势监听 onFling方法中,调用了mDecor.getRootWindo ...