Java 基础语法:异常

3001 字
15 分钟
Java 基础语法:异常

学习目标:

  • 掌握异常的分类体系
  • 熟悉常见异常
  • 掌握异常的处理
  • 掌握finally使用
  • 掌握如何自定义异常

异常概述#

什么是异常#

简单来说异常就是用来表示Java程序运行过程中的错误(信息)

网络中断, 用户输入信息, 读取不存在的文件

异常体系与分类#

image-20221014113421323
image-20221014113421323

在Java中Throwable作为所有错误跟异常的祖先类

根据错误的严重程度分

  • Error,: 比较严重的错误(代码处理不了, Jvm内部资源耗尽的错误) java.lang.StackOverflowError 栈溢出 java.lang.OutOfMemoryError 堆溢出
  • Exception: 错误程度小, 能够用代码进行处理
    • java.lang.ArithmeticException: / by zero 算数异常 /0
    • java.lang.NullPointerException 空指针异常
    • java.lang.ArrayIndexOutOfBoundsException 数组越界

根据处理方式的不同

  • 编译时异常(checked) : 编译阶段就会出现异常提醒,编译不通过
  • 运行时异常(unchecked): 编译通过, 但是运行时可能会出错(RuntimeException及其子类)

编译时异常与运行时异常有啥区别?

  • 运行时异常本身及其所有子类都是运行时异常,编译阶段不报错,程序运行时出现的,一般由于逻辑错误或者参数传递错误造成
  • 编译时异常:除了RuntimeException本身及其子类外的其他的异常都是编译时异常,作用在于提醒程序员检查.

Exception是运行时异常还是编译时异常

  • Exception是编译时异常和运行时异常的父类
  • 在自定义异常的时候,Exception作为编译时异常

异常的作用

  1. 查询bug报错信息
  2. 可以作为方法内部的一种特殊返回值,以便通知调用者底层执行的情况

常见异常#

image-20221014115608435
image-20221014115608435

常见异常
编译时异常:
java.lang.CloneNotSupportedException 克隆异常
java.io.FileNotFoundException 找不到文件
java.io.IOException IO操作异常
运行时异常
java.lang.ArithmeticException 算数异常
java.lang.NullPointerException 空指针异常
java.lang.ArrayIndexOutOfBoundsException 数组越界异常
java.lang.NumberFormatException 数字格式化异常
java.lang.ClassCastException 类型转换异常

异常处理#

jvm默认处理机制#

jvm默认异常处理流程

  1. 当我们代码在执行到,发生错误的地方。
  2. 一旦发生错误,jvm就会终止我们自己程序的运行,转而执行jvm自己的错误处理流程
  3. 在发生错误地方,收集错误信息,产生一个描述错误的对象
  4. 访问收集到的错误信息,将错误信息,输出到控制台窗口中(哪个线程,异常类型名, 异常原因, 哪个类哪个方法哪一行报错了)

执行过程

  • 如果错误产生在main方法中
    • 当我们的代码执行到错误行数之前,代码是正常执行的
    • 当我们的代码执行到错误行数时,JVM会终止程序的执行,抛出一个该异常信息封装成的对象
    • 将该对象中的异常信息,打印到控制台上,告诉程序员发生了什么问题
    • 发生错误之后的语句,都不执行了
  • 如果错误产生在main方法当中的另一个方法中
    • 当程序执行到该方法的错误行数时,JVM会终止程序的执行
      • 向上给方法的调用者抛出一个该异常信息封装成的对象
    • 一直向上抛出,直到抛给main方法,main方法最终抛给JVM
    • 发生异常之前的语句正常执行,但是之后的语句都不执行了
  • 默认处理机制仅针对运行时异常

捕获异常,自己处理#

try-catch#

单分支#

语法

方式一:
try{
// 可能出现异常的代码
}catch(异常类型 对象名){
// 对异常的处理操作
}
方式二:
try{
// 可能出现异常的代码
}catch(异常类型1 | 异常类型2 | 异常类型3 | 对象名){
// 对异常的处理操作
}

try-catch的执行:

  1. 如果try中代码运行时发生了错误,jvm在发生错误的代码处,收集错误信息
  2. try 块中在错误代码之后的代码,就不会在运行,jvm会跳转到相应的错误处理器中, 执行开发者自己写的,错误处理代码
  3. 错误处理器中的代码,一旦执行完毕紧接着,程序继续正常执行,执行的是整个try代码块之后的代码

注意:catch代码块中的代码,只有try块中的代码执行出错时,并且类型匹配成功才会执行!

捕获异常信息#

//获取异常信息,返回字符串。
getMessage()
//获取异常类名和异常信息,返回字符串。
toString()
//获取异常类名和异常信息,以及异常出现在程序中的位置,并打印到控制台
printStackTrace()

多分支#

语法

try{
// 可能出现异常的代码
}catch(异常类型 对象名){
// 对异常的处理操作
}catch(异常类型 对象名){
// 对异常的处理操作
}catch(异常类型 对象名){
// 对异常的处理操作
}.....

匹配规则: 1.根据实际的异常对象的类型,和异常分支(异常处理器)声明的异常类型,从上到下一次做类型匹配 2. 一旦通过类型匹配,发现实际异常对象的类型和Catch分支(异常处理器)声明的异常类型,类型匹配,就把异常对象交给这个异常分支(异常处理器) 3. 多分支的异常处理的执行,有点类似于多分支if-else的执行,一次匹配,只会执行多个catch分支中的一个

注意事项:

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

练习: 单独处理除0异常,空指针,数组下标越界异常一起处理。

try {
// 出现异常的代码
} catch (ArithmeticException e) {
System.out.println("xxxxxxx");
} catch (NullPointerException | ArrayIndexOutOfBoundsException e) {
System.out.println("sssssss");
}

抛出异常,上层处理#

当方法中出现了异常, 方法就没有继续执行下去的意义了, 可以选择抛出异常处理.

让该方法结束运行并告诉调用者发生了什么问题.

throws关键字#

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

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

解释说明:

  • 异常列表: 异常类型1, 异常类型2, … 用逗号隔开,列表中的异常不要出现父子关系,如果有,那么编译器只会强制处理父类
  • 只是声明可能抛出,到底抛不抛,看代码
  • throws+运行时异常没有意义,因为运行时异常会自动抛出,不需要声明.throws+编译时异常才有意义,这实际上是编译异常处理的一种方式
  • 在方法中声明throws+编译时异常,声明可能抛出编译时异常,该方法被调用时就要处理这个编译异常
  • 处理编译时异常
    • 方法内部try-catch
    • throws向上抛,如果在main中就别抛了,处理一下

子类重写父类方法注意:

  • 子类方法不能比父类抛出更多的编译时异常
  • 父类如果抛出Exception,那么子类就可以随便抛出
  • 建议子类重写的时候保持跟父类一样的异常列表

throw关键字#

在方法体中使用 主动在程序中抛出异常 每次只能抛出确定的某个异常对象

基本语法:

throw 异常对象 (new 出来的)

注意:

  • throw+编译时异常,需要结合throws关键字

throws vs throw#

throws

  • 用在方法声明后面,跟的是异常类名
  • 可以跟多个异常类名,用逗号隔开
  • 表示抛出异常,由该方法的调用者来处理
  • throws表示出现异常的一种可能性,并不一定会发生这些异常

throw

  • 用在方法体内,跟的是异常对象名
  • 只能抛出一个异常对象
  • 表示抛出异常,可以由方法体内的语句处理
  • throw则是抛出了异常,执行throw则一定抛出了某种异常

异常策略选择#

总结一下,目前为止,我们学习过的异常处理策略有2种:

  • 捕获并处理try-catch
  • 向上抛出
    • 运行时异常,自动抛出,直道抛给jvm
    • 编译时异常,需要结合throws关键字向上抛

如何选择策略?

  • 对于运行时异常,我们不应该写出产生这种异常的代码,应该在代码的测试阶段修正代码或者选择在方法调用处统一处理.
  • 对于编译时异常,功能内部能够处理的就处理,如果不能够或者没有必要处理,就抛出,由方法调用处统一处理.

finally#

特点

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

作用

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

如何使用

跟try-catch结合

语法:方式一
try{
}catch(){
}catch(){
}.....
finally{
// 一定执行
}
方式二:
try{
}finally{
}

一些奇思妙想

  • try代码块如果有return
    • 程序会先执行完finally代码块,回过头执行try中的return
  • catch代码块中如果有return,并且catch正常捕获异常执行
    • 程序会先执行完finally代码块后,再回去执行catch中return,从catch代码块中结束方法
  • finally代码中有return
    • 不会影响finally代码块执行
  • 如果finally和catch中都有return
    • 程序会直接从finally代码块中的return结束方法
  • 如果try中的异常不能正常捕获,但是finally中有return
    • 注意此时程序会跳过这个异常,不会抛出异常给JVM报错

final与finally有什么区别

  • final关键字,最终的,最后的。可以修饰类 成员变量 成员方法
    • 修饰类,该类不能被继承
    • 修饰变量表示一个常量
    • 修饰方法表示无法重写的方法
  • finally代码块,和try…catch一起使用,具有必然执行的特点
    • 异常处理体系当中,用于资源释放

自定义异常#

为什么要自定义异常#

现有的异常体系不满足需求

如何自定义异常#

自定义编译时异常#

  • 定义一个类继承Exception
  • 构造方法

自定义运行时异常#

  • 定义一个类继承RuntimeException
  • 构造方法

考试成绩必须在0-100分之间,如果有考试成绩不在这个范围之内,则认为成绩异常。

对于以上的异常,Java语言中显然没有一个对应的“考试分数异常超出范围”的异常,因此该异常需要我们自己来定义。

package _15exception.com.cskaoyan._06define;
import java.util.Scanner;
/**
* @description:
* @author: 景天
* @date: 2022/10/14 16:06
**/
/*
考试成绩必须在0-100分之间,如果有考试成绩不在这个范围之内,则认为成绩异常。
*/
public class Demo {
public static void main(String[] args) {
try {
func();
} catch (MyException1 myException1) {
myException1.printStackTrace();
}
}
private static void func() throws MyException1 {
// 键盘接收分数
Scanner scanner = new Scanner(System.in);
int score = scanner.nextInt();
// 判读一下是否在区间内
if (score < 0 || score > 100) {
// 如果不在 抛出异常
// throw + 异常对象
throw new MyException1("分数不合法");
}
}
}
// 定义编译时异常
class MyException1 extends Exception{
public MyException1() {
}
public MyException1(String message) {
super(message);
}
}
// 定义运行时异常
class MyException2 extends RuntimeException{
public MyException2() {
}
public MyException2(String message) {
super(message);
}
}

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

Java 基础语法:异常
https://firefly-mu-weld.vercel.app/posts/14-异常/
作者
Daisy
发布于
2026-06-10
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
Daisy
Hello, I'm Daisy.
公告
欢迎来到我的博客!这是一则示例公告。
分类
标签

文章目录