一文带你读懂Java异常

1、异常机制概述

异常机制是指当程序非正常时的处理方法。具体来说,异常机制提供了程序退出的安全通道。当出现错误后,程序执行的流程发生改变,程序的控制权转移到异常处理器。

程序异常分为编译时异常运行时异常。

(1)、编译时异常是因为在编写代码时,没有遵循语法规则,一般开发工具都能对编译异常进行提示;

(2)、运行时异常是程序运行后才会出现的异常,通常是编写代码时没有发现的。

 

2、Java中异常的分类

在Java中,所有异常都有一个共同的祖先:Throwable,所有异常类都由此类派生,请看下图:

图中我们看到,Error和Exception都继承自Throwable;

Error(错误):Error是程序无法进行处理的错误,它是由 JVM (Java 虚拟机)产生和抛出的,例如JVM系统内部错误、

                          资源耗尽(OutOfMemoryError)等,这些异常发生时,JVM一般会选择线程终止。

Exception(异常):Exception 是程序本身可以处理的异常,分为运行时异常(RuntimeException)和

                                   非运行时异常(Checked Exception),在程序中应当尽可能去处理这些异常。

 

3、重点讲解Exception

RuntimeException是一种Unchecked Exception,即编译器不会检查代码是否对异常进行了处理,在程序中无需抛出异常或者捕获异常。一般来说,这些异常是由代码编写者导致的,当出现这类异常时,应当及时修改代码bug。

常见的RuntimeException有如下几种

NullPointerException:空指针异常,这类异常多发生在没有对对象判空就取对象中的变量或方法,或者是使用null.equals()等;

NumberFormatException:类型转换异常,例如将String类型变量强行转为int类型,int i = Integer.parseInt("abc");

ArrayIndexOutOfBoundsException:数组下标越界异常,例如一个大小为3的String类型数组str,却设置str[3] = "abc";

ClassCastException:类型转换异常,例如将Cat转换为Dog。

 

非RuntimeException是Checked Exception,Java规定必须对checked Exception作处理,编译器会对此作检查,处理方法是抛出异常或捕获异常,不然不能通过编译。

常见的Checked Exception有如下几种

IOException:流操作异常,例如我们new FileInputStream()时就需要进行异常处理。

SQLException:sql异常,例如mybatis中对sql语法错误的异常处理。

 

4、Throwable中打印异常信息的方法

// 返回异常发生时的详细信息
public string getMessage();
 
// 返回异常发生时的简要描述
public string toString();
 
// 返回异常对象的本地化信息。使用Throwable的子类覆盖这个方法,可以声称本地化信息。
// 如果子类没有覆盖该方法,则该方法返回的信息与getMessage()返回的结果相同
public string getLocalizedMessage();
 
// 在控制台上打印Throwable对象封装的异常信息
public void printStackTrace();

 

5、异常处理方法

异常处理方法分为两种:

(1)、使用throws抛出异常,;

(2)、使用try - catch捕获异常;

 

throws用于在方法上将异常抛出,由方法的调用者对异常进行处理,而无需方法本身进行处理,语法形式如下:

public void test() throws Exception {
    ...
}

try - catch用于在方法内对异常进行捕获并处理,语法形式如下:

try {  
	// 可能会发生异常的程序代码  
} catch (xxException ex1){  
	// 捕获并处理try抛出的异常类型为ex1的异常  
} catch (xxException ex2){  
	// 捕获并处理try抛出的异常类型ex2的异常  
}

关键词try后的一对大括号将一块可能发生异常的代码包起来,称为监控区域

代码执行过程中,如果在监控区域发生异常,则try块会将异常进行抛出,并从上至下寻找catch中是否有定义与抛出异常类型相匹配的异常,若有,则执行相应catch块下的代码。

匹配的原则是:如果抛出的异常对象属于catch子句的异常类,或者属于该异常类的子类,则认为生成的异常对象与catch块捕获的异常类型相匹配。

注意

(1)、一旦某个catch捕获到匹配的异常类型,将进入异常处理代码。一经处理结束,就意味着整个try-catch语句结束。其他的               catch子句不再有匹配和捕获异常类型的机会。

(2)、对于有多个catch子句的异常程序而言,应该尽量将捕获底层异常类的catch子句放在前面,同时尽量将捕获相对高层的                异常类的catch子句放在后面。否则,捕获底层异常类的catch子句将可能会被屏蔽。

例如:RuntimeException异常类包括运行时各种常见的异常,ArithmeticException类和ArrayIndexOutOfBoundsException类都是它的子类。因此,RuntimeException异常类的catch子句应该放在最后面,否则可能会屏蔽其后的特定异常处理或引起编译错误。

try {
    ...
} catch(ArithmeticException e1) {
    ...
} catch(ArrayIndexOutOfBoundsException e2) {
    ...
} catch(RuntimeException e) {
    ...
}

 

6、异常包装

在 catch 子句中可以抛出一个异常,这样做的目的是改变异常的类型

try {
    …
} catch(SQLException e) {
    throw new ServletException(e.getMessage());
} 

这样的话 ServletException 会取代 SQLException。

有一种更好的方法,可以保存原有异常的信息,将原始异常设置为新的异常的原因

try {
    …
} catch(SQLException e) {
    Throwable se = new ServletException(e.getMessage());
    se.initCause(e);
    throw se;
}

当捕获到异常时,可以使用 getCause() 方法来重新得到原始异常

Throwable e = se.getCause();

建议使用这种包装技术,可以抛出系统的高级异常(自己 new 的),又不会丢失原始异常的细节。

早抛出,晚捕获。

 

7、throw和throws的区别

(1)、throw代表动作,表示抛出一个异常的动作;throws代表一种状态,代表方法有可能有异常抛出;

(2)、throw用于方法内手动抛出异常,而throws用于方法声明时;

(3)、throw只能用于抛出一种异常,而throws可以抛出多种异常。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值