Java中,所有的异常都来源于java.lang包中的Throwable类,它有两个重要的子类,Exception(异常)和Error(错误)。
在以下 2种特殊情况下,finally 块不会被执行:
代码示例:
BufferedReader br = null; try { br = new BufferedReader(new FileReader("test.txt")); br.readLine(); } catch (Exception e) { e.printStackTrace(); } finally { if (br != null) try { br.close(); } catch (IOException e) { e.printStackTrace(); } }
1. 适用范围(资源的定义): 任何实现 java.lang.AutoCloseable
的对象
2. 关闭资源和 finally 块的执行顺序: 在 try-with-resources
语句中,任何 catch 或 finally 块在声明的资源关闭后运行
《Effecitve Java》中明确指出:
面对必须要关闭的资源,我们总是应该优先使用 try-with-resources 而不是try-finally。随之产生的代码更简短,更清晰,产生的异常对我们也更有用。try-with-resources语句让我们更容易编写必须要关闭的资源的代码,若采用try-finally则几乎做不到这点。
将上面的代码例子改造:
try (BufferedReader br = new BufferedReader(new FileReader("test.txt"))) { br.readLine(); } catch (Exception e) { e.printStackTrace(); }
代码变得非常简洁。
注意:try-with-resource中声明的变量会隐式的加上final 关键字,所以无法再进行赋值。
在Java中要想创建自定义异常,需要继承Throwable或者他的子类Exception。
因为父类已经把异常信息的操作都完成了,所在子类只要在构造时,将异常信息传递给父类通过super 语句即可。
代码示例:
public class CustomException extends Exception { //无参构造方法 public CustomException(){ super(); } //有参的构造方法 public CustomException(String message){ super(message); } // 用指定的详细信息和原因构造一个新的异常 public CustomException(String message, Throwable cause){ super(message,cause); } //用指定原因构造一个新的异常 public CustomException(Throwable cause) { super(cause); } }
按照国际惯例,自定义的异常应该总是包含如下的构造函数:
finally块和return
首先一个不容易理解的事实:在 try块中即便有return,break,continue等改变执行流的语句,finally也会执行。
finally中的return 会覆盖 try 或者catch中的返回值。
finally中的return或异常会抑制(消灭)前面try或者catch块中的异常。