2109 字
11 min
0

异常处理

java是采用面向对象的方式来处理异常的。当程序出现问题时,就会创建异常类对象并抛出异常相关的信息(如异常出现的位置、原因等)。

异常概述

java是采用面向对象的方式来处理异常的。当程序出现问题时,就会创建异常类对象并抛出异常相关的信息(如异常出现的位置、原因等)。

异常分类

  1. 所有异常对象都是派生于Throwable类的一个实例。
  2. Thorwable类(表示可抛出)是所有异常和错误的超类,两个直接子类为ErrorException,分别表示错误和异常。

image-20250826163725400

Throwable

  1. Throwable类是所有异常或错误的超类,它有两个子类:ErrorException,分别表示错误和异常。其中异常Exception又分为运行时异常(RuntimeException)和编译时异常。
  2. Error和运行时异常,因为程序在编译时不检查异常,所以又称为不检查异常(Unchecked Exception)。
  3. 编译时异常,因为程序在编译时,异常可以被检查出,所以又称为可检查异常(Checked Exception)。
  4. Throwable常用方法:
    • public String getMessage():返回此throwable的详细消息字符串。
    • public String toString():返回此 throwable 的简短描述。
    • public void printStackTrace():打印异常的堆栈的跟踪信息。

Error

  1. Error类是java所有错误类的父类,描述了java运行时系统内部错误和资源耗尽错误。
  2. 这类错误是我们无法控制的,同时也是非常罕见的错误,表明系统JVM已经处于不可恢复的崩溃状态中。它是由JVM产生和抛出的,比如OutOfMemoryErrorThreadDeath等。
  3. 错误是很难处理的,一般的开发人员是无法处理这些错误的,我们在编程中,可以不去处理这类错误。

Exception

  1. Exception类是所有异常类的父类,其子类对应了各种各样可能出现的异常事件。
  2. Exception是程序本身可以处理的异常,在程序中应当尽可能去处理这些异常。
  3. Exception又分为两大类:
    • UncheckedException 未检查异常(运行时异常)
    • CheckedException 检查异常(编译时异常)

运行时异常

  1. RuntimeException及其子类异常,都属于运行时期异常。例如:ClassCastException、NullPointerException、IndexOutOfBoundsException、ArithmeticException等。
  2. 因为程序编译时异常不能被检查出,所以又称为不检查异常(UnCheckedException)。
  3. 运行时异常一般是由程序逻辑错误引起的,所以在编写程序时,我们应该从逻辑角度尽可能避免这类异常的发生。
  4. 当出现RuntimeException的时候,系统将自动检测并将它们交给缺省的异常处理程序(虚拟机接管并处理),用户可以不必对其处理。

编译时异常

  1. Exception及其子类(不包含运行异常),统称为编译时异常。
  2. 因为程序编译时异常可以被检查出,所以又称为可检查异常(CheckedException)。
  3. 常见的编译时异常:如IOException、SQLException等以及用户继承于Exception的自定义异常。
  4. 对于编译时异常,在编译时就强制要求我们必须对出现的这些异常进行处理,否则程序就不能编译通过。所以,面对这种异常不管我们是否愿意,都只能自己去处理可能出现的异常。

异常处理

抛出异常(throw)

  1. 在java语言中,提供了一个throw关键字,它用来抛出一个指定的异常对象。
  2. 在方法体中,使用throw关键字来抛出一个异常对象,将这个异常对象传递到调用者处,并结束当前方法的执行。

声明异常(throws)

  1. 声明:将问题标识出来,报告给调用者。如果方法内通过throw 抛出了编译时异常,而没有捕获处理,那么必须通过throws关键字进行声明,让调用者去处理。
  2. throws用于进行异常类的声明,若该方法可能有多种异常情况产生,那么在throws后面可以写多个异常类,用逗号隔开。
  3. 当程序中出现运行时异常时,方法定义中无需 throws 声明该异常,调用者也无需捕获处理该异常(即没有try-catch),系统会把异常一直默认往上层抛,一直抛到最上层。
  4. 当程序中出现非运行时异常时,要么用try-catch语句捕获它,要么用throws语句声明抛出它,否则编译不会通过。

捕获异常(try-catch-finally)

  1. 如果程序出现了异常,自己又解决不了,那么可以把异常声明出来(throws),报告给调用者,让调用者来做处理。
  2. 如果出现的异常自己能解决,那么就不用声明异常,而是自己捕获该异常(try-catch-finally),并在catch块中对该异常做处理。
  3. 一个try语句必须带有至少一个catch语句块或一个finally语句块 。

try-catch组合方式

  1. try-catch 组合:对代码进行异常检测,并对检测到的异常传递给 catch 处理。
  2. 一个try多个catch组合 : 对代码进行异常检测,并对检测的异常传递给catch处理。对每种异常信息进行不同的捕获处理。
  3. 这种异常处理方式,要求多个 catch 中的异常不能相同,并且若 catch 中的多个异常之间有子父类异常的关系,那么子类异常要求在上面的 catch 处理,父类异常在下面的 catch 处理。

try-catch-finally组合方式

  1. try-catch-finally组合:检测异常,并把捕捉到的异常传递给catch代码块处理,然后在finally中进行资源释放。
  2. 有一些特定的代码无论异常是否发生,都需要执行。另外,因为异常会引发程序跳转,导致有些语句执行不到。而 finally 就是解决这个问题的,在 finally 代码块中存放的代码都是一定会被执行的。
  3. 即使在try或catch中添加return,finally中的代码都会执行,除非调用System.exit(0);做退出虚拟机的操作,这样finally中的代码才不会执行。
  4. finally中添加return,则使用finally中的返回值。

try-finally组合方式

对代码进行异常检测,检测到异常后因为没有catch,所以一样会被默认 jvm 抛出。异常是没有捕获处理的。但是所开启的资源需要进行关闭,所有finally只为关闭资源。

自定义异常

  1. java中所有的异常类,都是继承Throwable,或者继承Throwable的子类。这样该异常才可以被throw抛出。
  2. 继承Exception属于非运行时异常,如果没有对其异常进行捕获处理(try-catch),那么必须在方法上声明异常(throws),以便告知调用者进行捕获。
  3. 继承RuntimeException属于运行时异常,方法上不需要声明异常(throws ),调用者也可以不捕获异常(try-catch)。代码一旦抛出异常,那么程序就会挂掉,并有JVM把异常信息显示到日志窗口上,让调用者看到异常并修改代码。

自定义异常的规范

  1. **命名规范:**自定义异常类名应以 Exception 结尾(如 InvalidParameterException),以明确标识异常类型‌。
  2. 继承关系:
    • 检查性异常(需强制处理)继承 Exception 类‌。
    • 非检查性异常(运行时异常)继承 RuntimeException 类‌。
    • 避免直接继承 ThrowableError‌。
  3. 序列化支持:若异常需跨网络传输或持久化,需实现 Serializable 接口,并显式声明 serialVersionUID
  4. 构造方法规范:
    • 空参构造方法:public CustomException() {}
    • 带错误信息的构造方法:public CustomException(String message)
    • 带错误信息和原因的构造方法:public CustomException(String message, Throwable cause)
  5. 封装额外信息:可添加自定义字段(如错误码、业务参数),便于定位问题‌。

方法重写中的异常

  1. 子类声明的异常范围不能超过父类声明范围。
  2. 子类重写父类方法时,不能抛出比父类更多的受检异常,可以选择不抛出异常或抛出更具体的异常‌。
  3. 子类在重写父类方法时,可以抛出新的运行时异常‌。

相关文章

评论区