还不理解 Error 和 Exception 吗,看这篇就够了( 二 )

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 。
什么是 ErrorError 是程序无法处理的错误,表示运行应用程序中较严重问题 。大多数错误与代码编写者执行的操作无关,而表示代码运行时 JVM(Java 虚拟机)出现的问题 。这些错误是不可检查的,因为它们在应用程序的控制和处理能力之 外,而且绝大多数是程序运行时不允许出现的状况,比如 OutOfMemoryError 和 StackOverflowError异常的出现会有几种情况,这里需要先介绍一下 Java 内存模型 JDK1.7 。
还不理解 Error 和 Exception 吗,看这篇就够了

文章插图


推荐阅读