异常

异常

表示java程序运行中的错误(信息)

java异常处理机制的由来
  • C语言时代的错误处理(程序员自觉处理)
  • java的基本理念:
    运行之前发现错误,但是有一些错误是编译器发现不了的错
  • 错误恢复机制(java异常处理机制)
    允许出错,但是一旦出错,有办法感知到这个错误并且进行补救。
    将错误向上报告。上级知道怎么处理错误就可以在语言层面自己处理这个错误,如果上级也不知道怎么处理的时候则将错误继续向上报告。最终报告给了jvm,
jvm有默认的处理方式

1、当代码在执行到发生错误的地方,
2、jvm会终止当前的程序,转入错误处理流程
3、在发生错误的地方,收集错误信息,产生一个描述错误的对象(异常对象)
4、访问收集到的信息,将错误的信息输出到控制台窗口中

jvm异常的分类
Exception:在程序中可能能够处理的错误
  • 编译时异常(Checkable Exception)
    可以预见的,语法层面强制在代码编写时处理
    本身代表的是编译时异常,他的直接子类也表示编译时异常(除了RunTimeException)
  • 运行时异常(RunTime Exception)
    本身代表的是运行时异常,他的直接子类也表示运行时异常
    不可预见的,不要求在编写代码时必须处理
区别

运行时异常
无需显示处理,也可以和编译时异常一样处理

编译时异常
Java程序必须显示处理,否则程序就会发生错误
无法通过编译

Error:

在程序层面无法处理的错误(致命的错误)

异常处理的语法

try{
//可能出现异常的,正常的代码逻辑
}catch(){//catch又叫异常处理器
//每一个catch分支对应一个异常处理器
//在catch分支中处理具体类型的代码异常
//错误记录到日志文件中
}
多分支异常匹配
  • 当在tru{}可能产生多种异常,但是在实际中,尝试不同的异常有不同的处理方法,所以定义多个catch,各司其职
    1、在catch(ArithmeticException e)
    2、在catch(ArrayIndexOutOfBoundsException e)
    3、在catch(NullPointerException e)

  • 如何区分不同异常分支(异常处理器)呢? 根据异常处理器所声明的不同的异常处理类型来区分, jvm 怎么知道,把异常对象交给哪个异常分支,并执行那个异常分支中的代码,这就存在一个多分支异常处理的匹配问题:
    1.根据实际的异常对象的类型,和异常分支(异常处理器)声明的异常类型,从上到下一次做类型匹配
    2.一旦通过类型匹配,发现实际异常对象的类型和Catch分支(异常处理器)声明的异常类型,类型匹配,就把异常对象交过
    这个异常分支(异常处理器)
    3.多分支的异常处理的执行,有点类似于多分支if-else的执行,一次匹配,只会执行多个catch分支中的一个

    • 注意事项:
      1如果说,在多catch分支的情况下,如果不同的catch分支,处理的异常类型,有父子关系,那么就一定要注意,处理子类的异常分支写在前面,父类的异常分支写在后面

      2不是包裹在try块中的代码,一旦产生了异常,都是自己来处理,只有try中异常类型, 有对应类型的异常处理器的时候

  • catch处理多分支语法

  • catch(xxxx|xxxx|xxxx){}

获取异常信息

getMessage()

获取异常信息,返回字符串。

toString()
获取异常类名和异常信息,返回字符串。
printStackTrace()
获取异常类名和异常信息,以及异常出现在程序中的位置,
并打印到控制台
printStackTrace(PrintStream s)
该方法将异常内容保存在日志文件中,以便查阅。

在Java中,与异常抛出有关的主要有两个关键字:

throws

在方法定义时使用
声明该方法可能抛出的异常
对于编译时异常,可以在语法层面强制方法调用者处理该异常

基本语法:

修饰符 返回值(形参列表) throws 异常列表 {}

注意事项:

异常列表之间用逗号分割,列表中出现的异常不要出现包含父子关系
方法覆盖时的子类异常列表必须与父类兼容
a. 当子类方法声明的异常类型和父类声明的异常类型,完全相同的时候,可以发生方法覆盖
b. 子类中声明的异常类型, 都是父类中声明异常列表中的异常的子类类型(只针对编译时异常)
c. 如果说父类没有异常列表,对于 编译时异常 而言,子类也不能有异常列表(子类也没有才能发生方法覆盖)
d. 如果说父类有异常列表,子类没有异常列表,不管是编译时异常,还是运行时异常,都可以发生方法覆盖

throws VS throw
  • throws
    用在方法声明后面,跟的是异常类名
    可以跟多个异常类名,用逗号隔开
    表示抛出异常,由该方法的调用者来处理
    throws表示出现异常的一种可能性,并不一定会发生这些异常
  • throw
    用在方法体内,跟的是异常对象名
    只能抛出一个异常对象
    表示抛出异常,可以由方法体内的语句处理
    throw则是抛出了异常,执行throw则一定抛出了某种异常

finally代码块

finally的特点

被finally控制的语句体一定会执行
特殊情况:在执行到finally之前jvm退出了(比如System.exit(0))

finally的作用

用于释放资源,在IO流操作和数据库操作中会见到

finally相关的面试题
  • final,finally和finalize的区别
    final用于声明属性,方法和类,分别表示属性不可交变,方法不可覆盖,类不可继承。
    finally是异常处理语句结构的一部分,表示总是执行。
    finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,供垃圾收集时的其他资源回收,例如关闭文件等。
  • 如果catch里面有return语句,请问finally的代码还会执行吗?
    如果会,请问是在return前还是return后
    会执行,但是return与finally并没有明显的谁强谁弱。在执行时,是return语句先把返回值写入但内存中,然后停下来等待finally语句块执行完,return再执行后面的一段。
    try…catch…finally可以使用
    try…catch也可以使用
    try…finally也可以使用
    但是,catch,finally不能单独使用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值