Java标准库内建了一些通用的异常,这些类以Throwable为顶层父类。Throwable又派生出Error类和Exception类。错误:Error类以及他的子类的实例,表明了JVM自己的错误。错误不能被程序员经过代码处理,Error不多出现。所以,程序员应该关注Exception为父类的分支下的各类异常类。异常:Exception以及他的子类,表明程序运行时发送的各类不指望发生的事件。能够被Java异常处理机制使用,是异常处理的核心。
html
整体上咱们根据Javac对异常的处理要求,将异常类分为2类。java
非检查异常(unckecked exception):Error 和 RuntimeException 以及他们的子类。javac在编译时,不会提示和发现这样的异常,不要求在程序处理这些异常。因此若是愿意,咱们能够编写代码处理(使用try…catch…finally)这样的异常,也能够不处理。对于这些异常,咱们应该修正代码,而不是去经过异常处理器处理 。这样的异常发生的缘由多半是代码写的有问题。如除0错误ArithmeticException,错误的强制类型转换错误ClassCastException,数组索引越界ArrayIndexOutOfBoundsException,使用了空对象NullPointerException等等。程序员
检查异常(checked exception):除了Error 和 RuntimeException的其它异常。javac强制要求程序员为这样的异常作预备处理工做(使用try…catch…finally或者throws)。在方法中要么用try-catch语句捕获它并处理,要么用throws子句声明抛出它,不然编译不会经过。这样的异常通常是由程序的运行环境致使的。由于程序可能被运行在各类未知的环境下,而程序员没法干预用户如何使用他编写的程序,因而程序员就应该为这样的异常时刻准备着。如SQLException , IOException,ClassNotFoundException 等。数据库
注意:检查异常是在编译时必须进行处理的异常,不然编译不会经过,要求强制进行处理。非检查异常(Runtime Exception)是运行时才会出现的异常,不须要在程序中作强制处理。非检查异常能够不作处理,即不要求在程序中用try catch捕获或者用throws本身抛出。编程
在编写代码处理异常时,对于检查异常,有2种不一样的处理方式:使用try…catch…finally语句块处理它。或者,在函数签名中使用throws 声明交给函数调用者caller去解决。数组
try…catch…finally语句块bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
try
{
//try块中放可能发生异常的代码。
//若是执行完try且不发生异常,则接着去执行finally块和finally后面的代码(若是有的话)。
//若是发生异常,则尝试去匹配catch块。
}
catch
(SQLException SQLexception){
//每个catch块用于捕获并处理一个特定的异常,或者这异常类型的子类。Java7中能够将多个异常声明在一个catch中。
//catch后面的括号定义了异常类型和异常参数。若是异常与之匹配且是最早匹配到的,则虚拟机将使用这个catch块来处理异常。
//在catch块中可使用这个块的异常参数来获取异常的相关信息。异常参数是这个catch块中的局部变量,其它块不能访问。
//若是当前try块中发生的异常在后续的全部catch中都没捕获到,则先去执行finally,而后到这个函数的外部caller中去匹配异常处理器。
//若是try中没有发生异常,则全部的catch块将被忽略。
}
catch
(Exception exception){
//...
}
finally
{
//finally块一般是可选的。
//不管异常是否发生,异常是否匹配被处理,finally都会执行。
//一个try至少要有一个catch块,不然, 至少要有1个finally块。可是finally不是用来处理异常的,finally不会捕获异常。
//finally主要作一些清理工做,如流的关闭,数据库链接的关闭等。
}
|
finally块无论异常是否发生,只要对应的try执行了,则它必定也执行。只有一种方法让finally块不执行:System.exit()。所以finally块一般用来作资源释放操做:关闭文件,关闭数据库链接等等。app
良好的编程习惯是:在try块中打开资源,在finally块中清理释放这些资源。函数
须要注意的地方:this
一、finally块没有处理异常的能力。处理异常的只能是catch块。
二、在同一try…catch…finally块中 ,若是try中抛出异常,且有匹配的catch块,则先执行catch块,再执行finally块。若是没有catch块匹配,则先执行finally,而后去外面的调用者中寻找合适的catch块。
三、在同一try…catch…finally块中 ,try发生异常,且匹配的catch块中处理异常时也抛出异常,那么后面的finally也会执行:首先执行finally块,而后去外围调用者中寻找合适的catch块。
首先一个不容易理解的事实:在 try块中即使有return,break,continue等改变执行流的语句,finally也会执行。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
public
static
void
main(String[] args)
{
int
re = bar();
System.out.println(re);
}
private
static
int
bar()
{
try
{
return
5
;
}
finally
{
System.out.println(
"finally"
);
}
}
/*输出:
finally
*/
|
注意:try .. catch ..finally语句块中至少有一个try,至少有一个catch或者finally。若是catch没有捕获到异常,会直接在finally中处理。
<1>finally中的return会覆盖try或catch块中的return返回值。
<2>若是在try中使用了return就不用执行catch中的语句,可是永远会执行finally中的语句,若是try中无retrun语句,在catch中抛出异常,而finally中使用了retrun,则catch中的语句不会被执行。
<3>若是同时在catch和finally中抛出异常,finally中抛出的异常
自定义异常
自定义异常能够按照如上图方式,定义一个父类业务异常继承自RuntimeException,子类异常继承自父类,父类异常中定义code,message,date属性。
RuntimeException源码:
public class RuntimeException extends Exception {
static final long serialVersionUID = -7034897190745766939L;
/** Constructs a new runtime exception with {@code null} as its
* detail message. The cause is not initialized, and may subsequently be
* initialized by a call to {@link #initCause}.
*/
public RuntimeException() {
super();
}
/** Constructs a new runtime exception with the specified detail message.
* The cause is not initialized, and may subsequently be initialized by a
* call to {@link #initCause}.
*
* @param message the detail message. The detail message is saved for
* later retrieval by the {@link #getMessage()} method.
*/
public RuntimeException(String message) {
super(message);
}
/**
* Constructs a new runtime exception with the specified detail message and
* cause. <p>Note that the detail message associated with
* {@code cause} is <i>not</i> automatically incorporated in
* this runtime exception's detail message. * * @param message the detail message (which is saved for later retrieval * by the {@link #getMessage()} method). * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method). (A <tt>null</tt> value is * permitted, and indicates that the cause is nonexistent or * unknown.) * @since 1.4 */ public RuntimeException(String message, Throwable cause) { super(message, cause); } /** Constructs a new runtime exception with the specified cause and a * detail message of <tt>(cause==null ? null : cause.toString())</tt> * (which typically contains the class and detail message of * <tt>cause</tt>). This constructor is useful for runtime exceptions * that are little more than wrappers for other throwables. * * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method). (A <tt>null</tt> value is * permitted, and indicates that the cause is nonexistent or * unknown.) * @since 1.4 */ public RuntimeException(Throwable cause) { super(cause); } /** * Constructs a new runtime exception with the specified detail * message, cause, suppression enabled or disabled, and writable * stack trace enabled or disabled. * * @param message the detail message. * @param cause the cause. (A {@code null} value is permitted, * and indicates that the cause is nonexistent or unknown.) * @param enableSuppression whether or not suppression is enabled * or disabled * @param writableStackTrace whether or not the stack trace should * be writable * * @since 1.7 */ protected RuntimeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); } }复制代码
public class BusinessException extends RuntimeException {
/**
* 业务信息编码
*/
private String code;
/**
* 业务信息编码
*/
private String errorMessage;
public BusinessException(String errorMessage) {
super(errorMessage);//调用父类带参构造函数,必须调用给Throwable超类中的message赋值,不然经过e.getMessage将取不到值
this.errorMessage = errorMessage;
}
}
复制代码