异常

声明: 本文主要作为作者的复习笔记,由于作者水平有限,难免有错误和不准确之处,欢迎读者批评指正.

异常

  • 在程序执行过程中,碰到某些代码执行不下去,这种称为异常; 编译阶段就报错的是语法错误,程序压根没有执行,不是异常;
  • 当程序出现了异常,从异常位置之后的代码就无法正常执行了;
  • 程序开发中碰到最多的三大类异常: 越界异常,空指针异常,类型转换异常;

越界异常: 索引下标非法;
空指针异常: 通过一个值为null的引用调用成员方法/属性;
类型转换异常: 发生在两个毫无关系的类之间对象的转换(要发生向下转型首先得发生向上转型);

在Java中,异常也是类,一切皆对象; 程序抛出的异常,其实抛出的是异常对象!!! 只不过这个对象是由JVM产生并返回给程序的;

异常体系核心的两个父类

  1. Error: JVM无法解决的严重问题,当出现Error类问题,程序是无法解决的只有退出;
    例:
    Error StackOverFlowError(栈溢出)
    OutOfMemoryError(堆溢出)
    原因: 程序中栈和堆的内存不够了;
  2. Exception: 异常产生后,程序员可以通过异常的处理流程来解决此类问题,使得程序能继续执行;

异常的另外划分模式(受查异常和非受查异常)

  1. 受查异常/编译时异常: 在程序编译时必须显示进行异常处理的异常,称为受查异常; 若不处理此异常,程序无法运行;
  2. 非受查异常/运行时异常: 程序编译时没有产生任何错误,但是程序执行时发生的异常称为非受查异常;

异常处理流程思路

  1. 先确保没问题,再执行;
  2. 先执行,出错了再处理;

异常处理的5个主要关键字: try、catch、finally、throw、throws

try{
	//可能产生异常的代码放在try代码块中
}[catch(异常类型 异常对象)] [0...N]{
	//若捕获到了相应类型的异常对象,放在catch代码块中
	//a.当异常产生,且被正确的捕获到; 走相应的catch代码块,try代码块中从出现异常之后的代码不再执行,异常体系之后的代码能够正确的执行
	//b.当没有异常产生时,不走catch块,程序正常执行结束
} [finally] {
	//无论是否有异常产生或者是否处理异常,最终一定会执行的代码放在finally代码块中
	//finally中的代码一定会被执行到
}
  • 有异常处理之后,保证程序抛出异常之后,正确捕获该异常,就可以使得异常体系之后的代码可以继续执行;
  • 异常也是类,在catch代码块中只能捕获一种类型的异常;
  • 可以使用多个catch块来捕获多种可能产生的异常,从上向下匹配,当异常匹配到满足的catch代码块就进入,其他的catch块就不再执行;
  • 当try中可能会产生多种异常时,可以使用多个catch块来捕获; 也可以捕获异常的父类(但不推荐),通过向上转型来进行异常捕获;
  • 若捕获到相应的异常之后,输出错误产生的原因以及出错的位置,通过异常对象的printStackTrace方法来进行打印输出;
  • 只要try中产生的不是Error错误,都能使用此处的catch代码块进行捕获;
  • catch代码块有多个分支,且多个分支有父子关系的情况,子类异常的捕获一定要写在父类异常之前!!! 若在定义时,父类异常写在子类异常之前,则子类异常永远不可能执行;
  • 无论是否有异常产生,且是否有返回值,JVM保证finally代码块一定会执行; 因此可以把所有关于资源关闭的操作,文件的关闭,数据库连接的关闭等统一都放在finally代码块中,确保该资源一定会被关闭;
  • 若finally有return语句,无论是否有异常产生,都会返回finally的返回值,因此一般不在finally中写return语句;
  • 正常编码,JVM会保证finally的正常执行; 若出现一些导致JVM进程直接退出的情况,finally才不会执行; 例如: System.exit(0);

throws

若出现异常,不处理,将异常抛回给调用者处理(甩锅操作);

若在整个调用过程中,没有一个位置处理异常,最终这个异常对象就会抛回给JVM,整个程序退出;

关键点:

  1. throws关键字在方法列表之后进行定义;
  2. throws可以抛出多个异常,多个异常使用","分隔,若有父子关系,只需要抛出父类异常即可;
  3. throws抛出的必须是Exception以及其子类;
  4. 若throws抛出的是受查异常,则调用者必须进行显示的异常处理(要么用try-catch捕获,要么继续通过throws向上抛出);

throw

用在方法内部,程序员在出现异常时,自己产生异常对象并向外抛出(原来异常对象是由JVM产生的,现在程序员自己产生异常对象),一般搭配自定义异常使用;

是否需要显示进行异常处理,跟怎么产生的异常对象无关,无论是哪种方式产生的异常对象,JVM产生的还是自己throw new出来的对象; 要看这个异常对象是受查异常还是非受查异常,只要是受查异常,无论哪种方式产生的异常对象,都必须显示进行异常处理;

关于自定义异常

之所以会有自定义异常的需求,是因为JDK内部提前定义好了很多的内置异常,这些异常在具体的业务场景下是不够用的;

  • 在写具体项目时,一定会有很多问题是和具体场景有关的; 比如用户名错误 => 不是语法错误,或者是密码错误; 这些问题JDK当然无从得知,所以就需要继承异常类,拓展属于自己的异常类;
  • 若需要拓展的是非受查异常,继承RuntimeException类;
  • 若需要拓展的是受查异常,继承Exception类;

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值