Java基础-异常

Java基础-异常

@[作者:JasonPeng, 版本 :1.0.0]



一、没有异常处理机制的困惑

没有异常处理机制存在的缺点:
①:使用方法的返回值来表示异常的情况有限,无法穷举到所有的异常情况。
②:异常流程代码和正常流程代码混合在一起,大大增加了程序的复杂性,可读性降低。
③:随着系统规模的不断扩大,程序的可维护性极低。

解决方案:
①:把不同类型的异常情况描述成类(称之为异常类)。
②:分离异常流程代码和正确的流程代码。
③:灵活处理异常,如果当前方法处理不了,应该交给调用者处理。

二、异常体系

非正常情况出现后程序会中断:
①:Error:表示错误,一般只JVM相关的不可修复的错误。如,系统崩溃,内存溢出,JVM错误等,有JVM抛出,我们不需要处理。几乎所有的子类都是以Error作为类名的后缀。
②:Exception:表示异常,指程序中出现的不正常的情况。该问题可以被修复(处理异常),几乎所有的子类都是以Exception作为类名的后缀。

三、捕获异常

(一)使用try-catch捕获单个异常

语法如下:

try{
    编写可能出现异常的代码
}catch(异常的类型 e){
    处理异常的代码
    // 记录日志、打印异常信息、继续抛出异常
}

注意:try和catch不能单独使用,必须连用。

(二)获取异常信息

Throwable类的方法:
①:String getMessage():获取异常的描述信息。原因(提示给用户的时候,就提示错误的原因)。
②:String toString():获取异常的类型和异常描述信息(不用)。
③:void printStackTrace():打印异常的跟踪栈信息并输出到控制台。包含了异常的类型,异常的原因,还包括了异常出现的位置,在开发和调试阶段,都要使用printStackTrace。

重要:在catch语句块中,必须写e.printStackTrace(),目的:查看异常的具体信息,方便调试和修改。

(三)使用try-catch捕获多个异常
try{
    编写可能会出现的异常代码
}catch(异常类型A e){ // 当try中出现A类型异常,就该catch来捕获
    处理异常的代码
    // 记录日志、打印异常信息、继续抛出异常
}catch(异常类型B e){ // 当try中出现B类型异常,就该catch来捕获
    处理异常的代码
    // 记录日志、打印异常信息、继续抛出异常
}

注意:
①:一个catch语句,只能捕获一种类型的异常,如果需要捕获多个异常,就得使用多个catch语句。
②:代码在一瞬间只能出现一种类型的异常,只需要一个catch捕获,不能同时出现多个异常。

四、finally代码块

finally语句块表示最终都会执行的代码,无论有没有异常。

什么时候代码必须最终执行:
当我们使用try语句块中打开了一些物理资源(磁盘文件、网络连接、数据库连接等),在使用完毕后,最终都要关闭打开的资源。

finally的两种语法:
①:try…finally:此时没有catch来捕获异常,因为此时根据应用场景,我们会抛出异常,自己不处理。
②:try…catch…finally:自身需要处理异常,最终还要关闭资源。

使用finally和不使用finally的区别,必须使用finally才能保证最终必须执行的代码。
如果finally有return语句,永远返回finally中的结果,要避免该情况。

五、异常分类

异常(Exception)的分类:
①:编译时期的异常:checked异常:在编译时期,就会检查,如果没有处理异常,则编译失败。
②:运行时期的异常:runtime异常:在运行时期,检查异常,在编译时期运行异常编译器不会检测(不报错)。
运行异常:在编译时期可处理,可不处理。

六、抛出异常

(一)throw语句

运用于方法内部,抛出一个具体的异常对象:

throw new 异常类("异常信息");终止方法。

一般当一个方法出现不正常情况的时候,我们不知道应该返回什么,此时就返回一个错误,在catch语句块中继续向上抛出异常。
return是返回一个值,throw是返回一个错误,返回给该方法的调用者。

(三)throws语句

运用于方法声明之上,用于表示当前方法不处理异常,而是提醒该方法的调用者来处理异常(抛出异常)。

private static int divide(int num1, int num2)throws Exception{}

如果每一个方法都放弃处理异常,都直接通过throws声明抛出,最后异常会跑到main方法,如果此时main方法不处理,继续抛出给JVM,底层的处理机制就是打印出异常的跟踪栈信息。

runtime异常,默认就是这种处理方式。

方法的覆盖(override):
一同:方法的签名必须相同。
两小:
①:子类方法返回类型和父类方法的返回类型相同或是其子类。
②:子类方法不能声明抛出新的异常。
一大:子类方法的访问权限必须大于等于父类方法的访问权限。

(四)自定义异常类

在开发中自己根据业务的异常情况来定义的异常类。
自定义异常类的定义:
①:自定义一个受检查的异常类:自定义类并继承于:java.lang.Exception。
②:自定义一个运行时期的异常类:自定义类并继承于:java.lang.RuntimeException。

(五)异常转义和异常链

①:异常转义:当位于最上层的子系统不需要关心底层的异常细节时,常常的做法是捕获原始的异常,把他转换为一个新的不同类型的异常,再抛出新的异常。
②:异常链:把原始的异常包装为新的异常类,从而形成多个异常的有序排列,有助于查找程序异常的根本原因。

七、Java7的异常新特性

①:增强throw
②:多异常捕获
③:自动资源关闭,必须实现AutoCloseable才能使用。

八、最佳实践

处理异常的原则:
①:异常只能用于非正常情况。
②:需要为异常提供说明文档,比如Java doc。
③:尽可能避免异常(如NullPointerException)。
④:异常的粒度很重要,应该为一个基本的操作定义一个try-catch块,不要为了简便,将几百行代码放到一个try-catch块中。
⑤:不建议在循环中进行异常的处理,应该在循环外对异常进行捕获处理。
⑥:自定义异常尽量是用RuntimeException类型的。


反馈与建议

感谢你阅读这篇博客。如果您喜欢这篇博客就请关注我和朋友一起分享吧!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值