2019独角兽企业重金招聘Python工程师标准>>>

我们在写Java的try..catch的时候,往往需要在最后加上finally子句关闭一些IO资源,比如

?

1
2
3
4
5
6
7
8
9
10
11
12
InputStream is;
try {
     is=openInputStream();
     // do something
} catch (IOException e){
     e.printStaceTrace(e);
} finally {
     try {
         is.close();
     } catch (IOException e ){
     }
}

但 是在使用这种模式时,即使是Java老手,偶尔也会犯一些错误。比如上面这段代码,当openInputStream()函数在执行过程中抛出异常,那么 变量is的值仍为null,此时执行is.close()会抛出NullPointerException. 由于NullPoiterException不是IOException的子类,因此它不能被catch块捕获,而是直接往调用层抛出去. 一种改进的写法就是在关闭流的时候先进行非空判断,但这样代码会显得很啰嗦。个人认为比较优雅的写法是直接调用commons-io包提供的 IOUtils.closeQuitely()方法关闭流(或者自己封装一个closeQuitely()方法)。

使用这种写法还有一种好处,就是当遇到关闭多个IO资源时不容易出错,比如下面这段代码:

?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
InputStream is;
OutputStream os ;
try {
     is=openInputStream();
     // do something
} catch (IOException e){
     e.printStaceTrace(e);
} finally {
     try {
         if  (is !=  null  )  is.close();
         if  (os !=  null  )  os.close();
     } catch (IOException e ){
     }
}

当is.close()发生错误的时候,os.close()就无法被执行,从而导致os所引用的资源没有被释放。

也许Oracle也觉得这种try .. catch ... finally的样板代码太没必要,因此在JDK 7中对try 子句进行了一些改造,免去编写一些手动关闭资源的代码,让代码看起来更紧凑更简洁。比如上面的代码在JDK 7下可以改成:

1
2
3
4
5
6
7
8
try (
  InputStream is = openInputStream();
  OutputStream os = openOutStream();
){
   // do something 
} catch (IOException e){
     e.printStaceTrace(e);
}

Oracle 把这里的try(..)语句叫做try-with-resource语句。需要注意的是,try(.. )中变量所引用的对象都必须是实现了java.io.AutoClosable接口的实例,当退出try ..catch块时,JDK会自动调用close()方法。 也就是说,try-with-resource语句中的resource(资源)不仅限于IO资源。

这里有必要对try-with-resource语句的一些细节进行补充说明:

  • JDK会确保所有资源的close()方法被调用,不管close()方法是否抛出异常, 而调用的顺序和资源声明的顺序相反

  • try-with-resource语句中所有抛出的异常都会被捕获。如果多个异常被抛出,后面所抛出的异常会被suppress(抑 制)在前一个异常中,catch块最终只拿到最先抛出的那个异常。可以依次通过调用Throwable类定义的getSuppressed()获得被 suppressed(抑制)的异常

还是上面那个例子,

  • 当退出try .. catch.块的时候,JDK会先调用os.close(),然后是is.close(), 如果两次close()都抛出IOException, 那么is.close()所抛出的异常会被suppress(抑制)在os.close()所抛出的异常中,最终catch块只捕获到 os.close()所抛出的异常。可以通过getSuppressed()方法拿到is.close()所抛出的异常。

  • 如果调用openInputStream()的时候就发生IOException,那么openOutputStream()就不会被调 用,os.close()和is.close()也不会被调用, catch块捕捉到 调用openInputStream()时所抛出的异常。

  • 如果调用openOutputStream()发生IOException(用记号 e1表示), 那么is.close()还是会被调用,  如果此时is.close()又抛出IOException(用记号 e2表示),那么e2会被suppress到e1中,而catch块捕捉到的异常是 e1.

除了对try块做了改造,JDK 7还对catch部分进行了简化,允许把多个catch子句合并。 比如:

?

1
2
3
4
5
6
7
8
try (
  InputStream is = openInputStream();
  OutputStream os = openOutStream();
){
   // do something   
} catch (IOException  | XMLParseException | XPathException e){
     e.printStaceTrace(e);
}

此外,当你重新抛出多个异常时,不再需要详细定义异常类型了,编译器已经知道你具体抛出的是哪个异常了。你只需在方法定义的时候声明需要抛出的异常即可。比如

?

1
2
3
4
5
6
7
8
// 虽然这里用Exception匹配抛出的IOException,到编译器知道实际上抛给上层的异常是IOException
         public  void  doIO()  throws  IOException {
             try {
                 throw  new  IOException();
             } catch (Exception e){
                 throw  e;
             }
         }

PS : 这个特性我想不到会带来什么好处

JDK 7还有其他有趣的语法新特性,比如二进制字面量,用下划线分割长数字,泛型参数的类型推断,switch支持字符串匹配等等。 现在JDK 8又引入了一些有用的特性。在不需要考虑向后兼容的前提下, 适当并灵活运用一些语法特性,可以让我们的代码在一定程度上显得更清晰,更简洁。

转载于:https://my.oschina.net/u/131940/blog/621652

谈谈Java的try..catch...相关推荐

  1. 谈谈 Java 类加载机制

    点击上方"方志朋",选择"置顶或者星标" 你的关注意义重大! 来源:Rainstorm , github.com/c-rainstorm/blog/blob/m ...

  2. 谈谈Java程序员进阶的那些知识和方向

    谈谈Java程序员进阶的那些知识和方向 记得前段时间看过一篇文章谈到一种程序员叫野生程序员,战斗力极强,可以搞定一切问题,但是通常看问题抓不到本质,或者说是google/baidu/stackover ...

  3. 谈谈 Java 的克隆

    转载自  谈谈 Java 的克隆 为什么要克隆对象 做开发很少用到克隆的.我能想得到的是用于调用方法时作为参数传递,为了保证方法调用前后对象的内部结构不被破坏,可以克隆一个对象作为参数传递. 使类具有 ...

  4. Android 性能优化 之谈谈Java内存区域

    最近一年副业主要在学习投资和技能学习,把以前学习内存分析的一些笔记总结发出来,写了很多笔记总结都没有写完就又忙着了,最近再次总结复习学习一遍,还有提醒各位同学一定要学会投资.. 了解Android 内 ...

  5. java多核并行计算_谈谈Java任务的并行处理

    前言 谈到并行,我们可能最先想到的是线程,多个线程一起运行,来提高我们系统的整体处理速度:为什么使用多个线程就能提高处理速度,因为现在计算机普遍都是多核处理器,我们需要充分利用cpu资源:如果站的更高 ...

  6. Java里try catch的简单用法

    Java里try catch的简单用法: Java里try catch的简单用法: 1.try+catch 程序的流程是:运行到try块中,如果有异常抛出,则转到catch块去处理.然后执行catch ...

  7. java stream 求和_谈谈Java任务的并行处理

    作者:ksfzhaohui 前言 谈到并行,我们可能最先想到的是线程,多个线程一起运行,来提高我们系统的整体处理速度:为什么使用多个线程就能提高处理速度,因为现在计算机普遍都是多核处理器,我们需要充分 ...

  8. Java 异常处理 try catch finally throws throw 的使用和解读(一)

    最近的一个内部表决系统开发过程中, 发现对异常处理还存在一些模棱两可的地方, 所以想着整理一下 主要涉及到: 1.try catch finally throws throw 的使用和解读 2.自定义 ...

  9. 谈谈JAVA中的安全发布

    谈谈JAVA中的安全发布 昨天看到一篇文章阐述技术类资料的"等级",看完之后很有共鸣.再加上最近在工作中越发觉得线程安全性的重要性和难以捉摸,又掏出了<Java并发编程实战& ...

最新文章

  1. Openoffice添加页脚页码页数页眉
  2. 网页编程从入门到精通 杨凡_干货 | web前端入门基础知识
  3. [html] 写一个密码默认星号,但可以查看密码的输入框
  4. 【CodeForces - 1041D】Glider (枚举起点,双指针 或 二分终点,思维)(知识点总结)
  5. 算法(17)-leetcode-剑指offer1
  6. 剑指offer(刷题21-30)--c++,Python版本
  7. 编写函数实现有序数组的二分查找
  8. JDBC连接数据库经验技巧集萃
  9. 第五次作业 刘惠惠 自动生成的方法存根
  10. Ubuntu 16.04如何安装Cinnamon 3.0
  11. 不宜猥琐惊世人 猥琐哥横空出世
  12. java设计模式之状态机模式
  13. 黑白照片如何变彩色?亲测好用的方法分享
  14. 线性代数学习笔记——第三十八讲——直线与直线的位置关系
  15. 大数据三篇论文—Google Bigtable中文版
  16. R语言加载xlsx报错错误: JAVA_HOME cannot be determined from the Registry解决方法
  17. 分享一个Java超市积分管理系统项目的制作方法。
  18. php 微信公众号企业转账功能
  19. 云计算大行其道 变革传统IT服务
  20. [杂谈][原创]海康威视H99 pro私有云盘使用体验

热门文章

  1. 什么是物联网?在生活中有何体现?
  2. 短短几分钟快速带你掌握C语言指南针!
  3. 四个措施打造安全的DevOps流程
  4. MATLAB R2018a 安装教程
  5. zTree入门实例(一眼就看会)
  6. ti processor sdk linux am335x evm /bin/setup-minicom.sh hacking
  7. 修改mysql的最大连接数
  8. OpenStack阵营将推VDI平台 挑战思杰、VMware
  9. 关于 TApplication 详解 六 ---- TColorDialog
  10. Java——类成员的访问权限修饰符(private、protected、public、default)