try...catch...finally 也是一样的,表示对异常捕获后,再走 finally 中的代码逻辑 。
JDK1.7 使用 try...with...resources 优雅关闭资源Java 类库中有许多资源需要通过 close 方法进行关闭 。比如 InputStream、OutputStream,数据库连接对象 Connection,MyBatis 中的 SqlSession 会话等 。作为开发人员经常会忽略掉资源的关闭方法,导致内存泄漏 。
根据经验,try-finally语句是确保资源会被关闭的最佳方法,就算异常或者返回也一样 。try-catch-finally 一般是这样来用的
static String firstLineOfFile(String path) throws IOException {BufferedReader br = new BufferedReader(new FileReader(path));try {return br.readLine();}finally {br.close();}}
这样看起来代码还是比较整洁,但是当我们添加第二个需要关闭的资源的时候,就像下面这样
static void copy(String src,String dst) throws Exception{InputStream is = new FileInputStream(src);try {OutputStream os = new FileOutputStream(dst);try {byte[] buf = new byte[100];int n;while ((n = is.read()) >= 0){os.write(buf,n,0);}}finally {os.close();}}finally {is.close();}}
这样感觉这个方法已经变得臃肿起来了 。
而且这种写法也存在诸多问题,即使 try - finally 能够正确关闭资源,但是它不能阻止异常的抛出,因为 try 和 finally 块中都可能有异常的发生 。
比如说你正在读取的时候硬盘损坏,这个时候你就无法读取文件和关闭资源了,此时会抛出两个异常 。但是在这种情况下,第二个异常会抹掉第一个异常 。在异常堆栈中也无法找到第一个异常的记录,怎么办,难道像这样来捕捉异常么?
static void tryThrowException(String path) throws Exception {BufferedReader br = new BufferedReader(new FileReader(path));try {String s = br.readLine();System.out.println("s = " + s);}catch (Exception e){e.printStackTrace();}finally {try {br.close();}catch (Exception e){e.printStackTrace();}finally {br.close();}}}
这种写法,虽然能解决异常抛出的问题,但是各种 try-cath-finally 的嵌套会让代码变得非常臃肿 。
Java7 中引入了try-with-resources 语句时,所有这些问题都能得到解决 。要使用 try-with-resources 语句,首先要实现 AutoCloseable 接口,此接口包含了单个返回的 close 方法 。Java 类库与三方类库中的许多类和接口,现在都实现或者扩展了 AutoCloseable 接口 。如果编写了一个类,它代表的是必须关闭的资源,那么这个类应该实现 AutoCloseable 接口 。
java 引入了 try-with-resources 声明,将 try-catch-finally 简化为 try-catch,这其实是一种语法糖,在编译时会进行转化为 try-catch-finally 语句 。
下面是使用 try-with-resources 的第一个范例
/*** 使用try-with-resources 改写示例一* @param path* @return* @throws IOException*/static String firstLineOfFileAutoClose(String path) throws IOException {try(BufferedReader br = new BufferedReader(new FileReader(path))){return br.readLine();}}
使用 try-with-resources 改写程序的第二个示例
static void copyAutoClose(String src,String dst) throws IOException{try(InputStream in = new FileInputStream(src);OutputStream os = new FileOutputStream(dst)){byte[] buf = new byte[1000];int n;while ((n = in.read(buf)) >= 0){os.write(buf,0,n);}}}
使用 try-with-resources 不仅使代码变得通俗易懂,也更容易诊断 。以firstLineOfFileAutoClose方法为例,如果调用 readLine() 和 close() 方法都抛出异常,后一个异常就会被禁止,以保留第一个异常 。
异常处理的原则我们在日常处理异常的代码中,应该遵循三个原则
- 不要捕获类似 Exception 之类的异常,而应该捕获类似特定的异常,比如 InterruptedException,方便排查问题,而且也能够让其他人接手你的代码时,会减少骂你的次数 。
- 不要生吞异常 。这是异常处理中要特别注重的事情,因为很可能会非常难以正常结束情况 。如果我们不把异常抛出来,或者也没有输出到 Logger 日志中,程序可能会在后面以不可控的方式结束 。
- 不要在函数式编程中使用 checkedException 。
文章插图
推荐阅读
- 诸葛亮如果北伐成功,诸葛亮为什么急于北伐
- 普洱茶厂家最新排名,还有染色普洱茶
- 王莽是刘秀所灭还是刘玄,刘玄之后谁做了皇帝
- 饭后锻炼还是饭前锻炼比较好?
- 袁大头|有人说一枚袁大头价值百万,还能换一套房,是真的吗?
- 曹操对关羽这么好为什么还要走,关羽投奔曹操的原因
- 姜维为什么一直要北伐,刘禅投降姜维说了什么
- 新浪微博|刘畊宏称自己还没有50岁:请注意我的身体年龄!
- 怀牛膝可以直接泡水喝吗,肾阳虚的人可以喝川牛膝和怀牛膝泡水吗或者是单独种可以还有舒筋草肾阳虚的人可以喝吗
- 空手道适合女生学吗还是跆拳道好呢