简述java异常机制处理,java异常机制

Java异常的分类和类结构图

Java标准库内建了一些通用的异常,这些类以Throwable为顶层父类。Throwable又派生出Error类和Exception类。错误:Error类以及他的子类的实例,代表了JVM本身的错误。错误不能被程序员通过代码处理,Error很少出现。因此,程序员应该关注Exception为父类的分支下的各种异常类。异常:Exception以及他的子类,代表程序运行时发送的各种不期望发生的事件。可以被Java异常处理机制使用,是异常处理的核心。

ea478f627d74cbdff1f6a59a2e510a69.png

总体上我们根据Javac对异常的处理要求,将异常类分为2类。

非检查异常(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语句块

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21try{

//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块

finally块不管异常是否发生,只要对应的try执行了,则它一定也执行。只有一种方法让finally块不执行:System.exit()。因此finally块通常用来做资源释放操作:关闭文件,关闭数据库连接等等。

良好的编程习惯是:在try块中打开资源,在finally块中清理释放这些资源。

需要注意的地方:

1、finally块没有处理异常的能力。处理异常的只能是catch块。

2、在同一try…catch…finally块中 ,如果try中抛出异常,且有匹配的catch块,则先执行catch块,再执行finally块。如果没有catch块匹配,则先执行finally,然后去外面的调用者中寻找合适的catch块。

3、在同一try…catch…finally块中 ,try发生异常,且匹配的catch块中处理异常时也抛出异常,那么后面的finally也会执行:首先执行finally块,然后去外围调用者中寻找合适的catch块。

finally块和return

首先一个不容易理解的事实:在 try块中即便有return,break,continue等改变执行流的语句,finally也会执行。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16public 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中抛出的异常

不要在fianlly中使用return。

不要在finally中抛出异常。

减轻finally的任务,不要在finally中做一些其它的事情,finally块仅仅用来释放资源是最合适的。

将尽量将所有的return写在函数的最后面,而不是try … catch … finally中。

自定义异常

53619e2ed18e47215082e004363bfb89.png

自定义异常可以按照如上图方式,定义一个父类业务异常继承自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.

Note that the detail message associated with

* {@code cause} is not 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 null 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 (cause==null ? null : cause.toString())

* (which typically contains the class and detail message of

* cause). 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 null 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;

}

}

复制代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值