Java异常学习总结

2023-11-06

1.什么是异常

异常本质上是程序上的错误,包括程序逻辑错误和系统错误

在Java中异常被当做对象来处理,根类是java.lang.Throwable类,在Java中定义了很多异常类(如OutOfMemoryError、NullPointerException、IndexOutOfBoundsException等),这些异常类分为两大类:Error和Exception。

  Error是无法处理的异常,比如OutOfMemoryError,一般发生这种异常,JVM会选择终止程序。因此我们编写程序时不需要关心这类异常。

  Exception,也就是我们经常见到的一些异常情况,比如NullPointerException、IndexOutOfBoundsException,这些异常是我们可以处理的异常。

  Exception类的异常包括checked exception和unchecked exception(unchecked exception也称运行时异常RuntimeException,当然这里的运行时异常并不是前面我所说的运行期间的异常,只是Java中用运行时异常这个术语来表示,Exception类的异常都是在运行期间发生的)。

  unchecked exception(非检查异常),也称运行时异常(RuntimeException),比如常见的NullPointerException、IndexOutOfBoundsException。对于运行时异常,java编译器不要求必须进行异常捕获处理或者抛出声明,由程序员自行决定。

  checked exception(检查异常),也称非运行时异常(运行时异常以外的异常就是非运行时异常),java编译器强制程序员必须进行捕获处理,比如常见的IOExeption和SQLException。对于非运行时异常如果不进行捕获或者抛出声明处理,编译都不会通过。

异常类的结构层次图如下图所示:

 

       在Java中,所有异常类的父类是Throwable类,Error类是error类型异常的父类,Exception类是exception类型异常的父类,RuntimeException类是所有运行时异常的父类,RuntimeException以外的并且继承Exception的类是非运行时异常。

  典型的RuntimeException包括NullPointerException、IndexOutOfBoundsException、IllegalArgumentException等。

  典型的非RuntimeException包括IOException、SQLException等。

2.处理异常

 在Java中如果需要处理异常,必须先对异常进行捕获,然后再对异常情况进行处理。如何对可能发生异常的代码进行异常捕获和处理呢?使用try和catch关键字即可,如下面一段代码所示:

try {
  File file = new File("d:/a.txt");
  if(!file.exists())
    file.createNewFile();
} catch (IOException e) {
  // TODO: handle exception
}

被try块包围的代码说明这段代码可能会发生异常,一旦发生异常,异常便会被catch捕获到,然后需要在catch块中进行异常处理。

  这是一种处理异常的方式。在Java中还提供了另一种异常处理方式即抛出异常,顾名思义,也就是说一旦发生异常,我把这个异常抛出去,让调用者去进行处理,自己不进行具体的处理,此时需要用到throw和throws关键字。 

下面看一个示例:

public class Main {
    public static void main(String[] args) {
        try {
            createFile();
        } catch (Exception e) {
            // TODO: handle exception
        }
    }
     
    public static void createFile() throws IOException{
        File file = new File("d:/a.txt");
        if(!file.exists())
            file.createNewFile();
    }
}

 

       这段代码和上面一段代码的区别是,在实际的createFile方法中并没有捕获异常,而是用throws关键字声明抛出异常,即告知这个方法的调用者此方法可能会抛出IOException。那么在main方法中调用createFile方法的时候,采用try...catch块进行了异常捕获处理。

  当然还可以采用throw关键字手动来抛出异常对象。下面看一个例子:

public class Main {
    public static void main(String[] args) {
        try {
            int[] data = new int[]{1,2,3};
            System.out.println(getDataByIndex(-1,data));
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
         
    }
     
    public static int getDataByIndex(int index,int[] data) {
        if(index<0||index>=data.length)
            throw new ArrayIndexOutOfBoundsException("数组下标越界");
        return data[index];
    }
}

然后在catch块中进行捕获。

  也就说在Java中进行异常处理的话,对于可能会发生异常的代码,可以选择三种方法来进行异常处理:

  1)对代码块用try..catch进行异常捕获处理;

  2)在 该代码的方法体外用throws进行抛出声明,告知此方法的调用者这段代码可能会出现这些异常,你需要谨慎处理。此时有两种情况:

    如果声明抛出的异常是非运行时异常,此方法的调用者必须显示地用try..catch块进行捕获或者继续向上层抛出异常。

    如果声明抛出的异常是运行时异常,此方法的调用者可以选择地进行异常捕获处理。

  3)在代码块用throw手动抛出一个异常对象,此时也有两种情况,跟2)中的类似:

    如果抛出的异常对象是非运行时异常,此方法的调用者必须显示地用try..catch块进行捕获或者继续向上层抛出异常。

    如果抛出的异常对象是运行时异常,此方法的调用者可以选择地进行异常捕获处理。

  (如果最终将异常抛给main方法,则相当于交给jvm自动处理,此时jvm会简单地打印异常信息)

3.深刻理解try,catch,finally,throws,throw五个关键字

下面我们来看一下异常机制中五个关键字的用法以及需要注意的地方。

1.try,catch,finally

  try关键字用来包围可能会出现异常的逻辑代码,它单独无法使用,必须配合catch或者finally使用。Java编译器允许的组合使用形式只有以下三种形式:

  try...catch...;       try....finally......;    try....catch...finally...

  当然catch块可以有多个,注意try块只能有一个,finally块是可选的(但是最多只能有一个finally块)。

  三个块执行的顺序为try—>catch—>finally。

  当然如果没有发生异常,则catch块不会执行。但是finally块无论在什么情况下都是会执行的(这点要非常注意,因此部分情况下,都会将释放资源的操作放在finally块中进行)。

  在有多个catch块的时候,是按照catch块的先后顺序进行匹配的,一旦异常类型被一个catch块匹配,则不会与后面的catch块进行匹配。

  在使用try..catch..finally块的时候,注意千万不要在finally块中使用return,因为finally中的return会覆盖已有的返回值。下面看一个例子:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
 
 
public class Main {
    public static void main(String[] args) {
        String str = new Main().openFile();
        System.out.println(str);
         
    }
     
    public String openFile() {
        try {
            FileInputStream inputStream = new FileInputStream("d:/a.txt");
            int ch = inputStream.read();
            System.out.println("aaa");
            return "step1";
        } catch (FileNotFoundException e) {
            System.out.println("file not found");
            return "step2";
        }catch (IOException e) {
            System.out.println("io exception");
            return "step3";
        }finally{
            System.out.println("finally block");
            //return "finally";
        }
    }
}

这段程序的输出结果为:

 

可以看出,在try块中发生FileNotFoundException之后,就跳到第一个catch块,打印"file not found"信息,并将"step2"赋值给返回值,然后执行finally块,最后将返回值返回。

  从这个例子说明,无论try块或者catch块中是否包含return语句,都会执行finally块。

  如果将这个程序稍微修改一下,将finally块中的return语句注释去掉,运行结果是:

 

最后打印出的是"finally",返回值被重新覆盖了。

  因此如果方法有返回值,切忌不要再finally中使用return,这样会使得程序结构变得混乱。

 2.throws和thow关键字

  1)throws出现在方法的声明中,表示该方法可能会抛出的异常,然后交给上层调用它的方法程序处理,允许throws后面跟着多个异常类型;

  2)一般会用于程序出现某种逻辑时程序员主动抛出某种特定类型的异常。throw只会出现在方法体中,当方法在执行过程中遇到异常情况时,将异常信息封装为异常对象,然后throw出去。throw关键字的一个非常重要的作用就是 异常类型的转换(会在后面阐述道)。

  throws表示出现异常的一种可能性,并不一定会发生这些异常;throw则是抛出了异常,执行throw则一定抛出了某种异常对象。两者都是消极处理异常的方式(这里的消极并不是说这种方式不好),只是抛出或者可能抛出异常,但是不会由方法去处理异常,真正的处理异常由此方法的上层调用处理。

四.在类继承的时候,方法覆盖时如何进行异常抛出声明 

 本小节讨论子类重写父类方法的时候,如何确定异常抛出声明的类型。下面是三点原则:

  1)父类的方法没有声明异常,子类在重写该方法的时候不能声明异常;

  2)如果父类的方法声明一个异常exception1,则子类在重写该方法的时候声明的异常不能是exception1的父类;

  3)如果父类的方法声明的异常类型只有非运行时异常(运行时异常),则子类在重写该方法的时候声明的异常也只能有非运行时异常(运行时异常),不能含有运行时异常(非运行时异常)。

 转载地址:Java异常处理和设计 - Matrix海子 - 博客园

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java异常学习总结 的相关文章

  • 任务“:app:dexDebug”执行失败

    我目前正在处理我的项目 我决定将我的 Android Studio 更新到新版本 但在我导入项目后 它显示如下错误 Information Gradle tasks app assembleDebug app preBuild UP TO
  • java中的csv到pdf文件

    我正在尝试获得一个csv文件解析为pdf 到目前为止我所拥有的内容附在下面 我的问题是这段代码最终出现在 pdf 中的文件在 csv 文件的第一行被截断 我不明白为什么 附示例 本质上我想要一个没有任何操作的 csv 文件的 pdf 版本
  • 如何对 IntStream 进行逆序排序

    我正在使用 txt 文件读取数字BufferedReader 我想颠倒该流中元素的顺序 以便在收集它们时 它们将从最高到最低排列 我不想在构建数组后进行排序 因为我不知道其中可能有多少元素 我只需要最高的 N 个元素 in new Buff
  • 方法断点可能会大大减慢调试速度

    每当向方法声明行添加断点 在 Intellij IDEA 或 Android Studio 中 时 都会出现一个弹出窗口 方法断点可能会大大减慢调试速度 为什么会这样戏剧性地减慢调试速度 是我的问题吗 将断点放在函数的第一行有什么不同 Th
  • JavaFX - setVisible 隐藏元素但不重新排列相邻节点

    在 JavaFX 中 如果我有一个场景有 2VBox元素和每个VBox有多个Label in it 如果我设置顶部VBox to 无形的 为什么底部VBox 不向上移动顶部的场景VBox was The VBox is 无形的但我希望其他物
  • Java 变量的作用域

    我不明白为什么这段代码的输出是10 package uno public class A int x 10 A int x 12 new B public static void main String args int x 11 new
  • 服务器到 Firebase HTTP POST 结果为响应消息 200

    使用 Java 代码 向下滚动查看 我使用 FCM 向我的 Android 发送通知消息 当提供正确的服务器密钥令牌时 我收到如下所示的响应消息 之后从 FCM 收到以下响应消息 Response 200 Success Message m
  • spring - 强制 @Autowired 字段的 cglib 代理

    我有混合堆栈 EJB 和 Spring 为了将 Spring 自动装配到 EJB 我使用SpringBeanAutowiringInterceptor 不确定这是否会影响我遇到的问题 在尝试通过以下方式自动装配 bean 时 Scope p
  • 如何将 XMP XML 块序列化为现有的 JPEG 图像?

    我有许多 JPEG 图像 其中包含损坏的 XMP XML 块 我可以轻松修复这些块 但我不确定如何将 固定 数据写回图像文件 我目前正在使用 JAVA 但我愿意接受任何能让这项任务变得容易的事情 这是目标关于 XMP XML 的另一个问题
  • Java替换特定字符

    这是我在这个网站上的第一个问题 所以我会尽量不要成为一个十足的菜鸟 我目前正在用java 创建刽子手游戏 所以我问你的问题是我们是否被赋予了 幽灵 这个词 并将 Ghost 替换为 hiddenWord ghost length for i
  • @EnableTransactionManagement 的范围是什么?

    我试图了解正确的放置位置 EnableTransactionManagement多个 JavaConfig 上下文的情况下的注释 考虑以下场景 我在 JPAConfig java 和 AppConfig java 中有 JPA 配置以及一组
  • 尝试在没有 GatewayIntent 的情况下访问消息内容

    我希望每当我写一条打招呼的消息时 机器人都会在控制台中响应一条消息 但它只是给我一个错误 JDA MainWS ReadThread WARN JDA Attempting to access message content without
  • Install4j:如何在安装结束时执行命令行 java -jar filename.jar

    在 Intall4j 中 在安装结束时 我只想通过执行如下命令行来初始化某些内容 java jar filename jar 我怎样才能归档这个任务install4j Thanks 将 运行可执行文件或批处理文件 操作添加到 安装屏幕 并设
  • 具有多种值类型的 Java 枚举

    基本上我所做的是为国家编写一个枚举 我希望不仅能够像国家一样访问它们 而且还能够访问它们的缩写以及它们是否是原始殖民地 public enum States MASSACHUSETTS Massachusetts MA true MICHI
  • 从 Java 日历迁移到 Joda 日期时间

    以前 当我第一次设计股票应用相关软件时 我决定使用java util Date表示股票的日期 时间信息 后来我体会到了大部分方法java util Date已弃用 因此 很快 我重构了所有代码以利用java util Calendar 然而
  • 如何在keycloak中动态编辑standalone.xml文件

    我正在尝试通过 docker 编辑standalone xml 并尝试添加 但 keycloak 正在使用它standalone xml 但我可以看到standalone xml 文件中的更改 我需要在standalone xml 文件中添
  • ExceptionHandler 不适用于 Throwable

    我们的应用程序是基于 Spring MVC 的 REST 应用程序 我正在尝试使用 ExceptionHandler 注释来处理所有错误和异常 I have ExceptionHandler Throwable class public R
  • 使用 Java 从 S3 上的文件在 S3 上创建 zip 文件

    我在 S3 上有很多文件 需要对其进行压缩 然后通过 S3 提供压缩文件 目前 我将它们从流压缩到本地文件 然后再次上传该文件 这会占用大量磁盘空间 因为每个文件大约有 3 10MB 而且我必须压缩多达 100 000 个文件 所以一个 z
  • 从java中的字符串数组中删除空值

    java中如何从字符串数组中删除空值 String firstArray test1 test2 test4 我需要像这样没有 null 空 值的 firstArray String firstArray test1 test2 test4
  • java中如何找到class文件的包

    我正在编写一个使用 class 文件的 java 程序 我希望能够读取文件系统上的 class 文件 使用 InputStream 并确定它所在的包 该 class 文件可能不在一个好的包目录结构中 它可能位于某个随机位置 我怎样才能做到这

随机推荐

  • LeetCode——反转字符串中的元音字母

    LeetCode 反转字符串中的元音字母 题目描述 编写一个函数 以字符串作为输入 反转该字符串中的元音字母 示例 1 输入 hello 输出 holle 示例 2 输入 leetcode 输出 leotcede 提示 元音字母不包含字母
  • 常用的计算机技术检索有哪几种,在计算机检索中,常用的布尔逻辑算符有哪几种...

    在计算机检索中 常用的布尔逻辑算符有哪几种 答案 1 信息版本 手机版 解决时间 2018 12 25 13 02 已解决 2018 12 24 15 15 在计算机检索中 常用的布尔逻辑算符有哪几种 最佳答案 2018 12 24 16
  • 【C++】程序的内存模型-内存四区

    1 内存分区模型 2 代码区 3 全局区 4 栈区 指针相关知识 https blog csdn net daidai10086 article details 118893241 5 堆区 6 new运算符
  • 启动Microsoft Office时出现“无法验证该产品的许可证“Office 应用

    项目 2021 12 09 适用于 Office Professional Plus 2016 Office Standard 2016 Access 2016 Excel 2016 Microsoft Publisher 2016 One
  • JS加密在网页安全中的应用及逆向分析方法

    在当今互联网时代 网页加密技术的应用越来越广泛 在网页中 常见的加密方式包括三种 flash加密 密码控件加密和JS加密 虽然这三种方式各有优劣 但JS加密是目前最为普遍和灵活的加密方式 JS加密的广泛应用主要源于它的灵活性和易用性 与fl
  • vue-cli3搭建及vue.config.js配置(配置文件完整且不报错)

    如果你已经安装了vue 2 9 6 的话 则需要先将其删除指令为 npm uninstall g vue cli 第二步 更新Vue cli 指令 npm install g vue cli 或 cnpm install g vue cli
  • 2023最新渗透学习路线,手把手带你从零基础进阶渗透攻防工程师

    要成为一名渗透测试员 想从基础学习需要先掌握下面这3块 文末有相关自学资源推荐 1 学习硬件和网络 渗透测试主要涉及网络和部分涉及硬件 2 操作系统和系统架构 操作系统和系统架构在渗透测试中起着关键作用 系统操作涉及x86 32位 和x64
  • RSA算法研究报告

    摘 要 分析RSA算法的应用现状 论证文件加密应用RSA算法的可行性和意义 设计一套完整实用的RSA文件加密解决方案 具体编码实现 对RSA算法进行研究 从常规RSA算法出发 用C 实现RSA加密算法类库 并在32位windows平台封装成
  • python如何编程-如何入门Python编程

    Python目前已经成为受欢迎的编程语言之一 吸引了一大批粉丝 但是很多人在要跨入的时候犹豫了 原因竟然是觉得学习Python太难了 真的是这样吗 入门Python编程学习有什么好的技巧吗 Python因为其清晰易读的风格 广泛的适用性 P
  • Golang 解决跨域问题, 处理http设置header无效

    今天遇到跨域问题 设置了如下配置 w WriteHeader http StatusOK w Header Set Access Control Allow Origin w Header Add Access Control Allow
  • 【数据库】第六章总结-关系数据理论

    如何设计一个好的表的结构 通过 关系数据库的规范化理论 我们简化一个 关系模式 R
  • python--字典版学生成绩管理系统

    目录 全局变量定义 菜单方法 添加学生信息 删除学生信息 修改学生成绩 查找学生信息 统计学生最高分 平均分 最低分 主运行函数 全部源代码 实现对学生信息的添加 删除 修改 查询操作 全局变量定义 import math 定义一个空字典存
  • Fractional-strided convolution,分数阶卷积,也称为转置卷积或反卷积

    Fractional strided convolution 分数阶卷积 也称为转置卷积或反卷积 是一种用于深度学习和计算机视觉的技术 用于对输入图像进行上采样或增加空间分辨率 与执行下采样的常规卷积层不同 分数步幅卷积层执行上采样 在常规
  • 奇偶交换排序

    已知奇偶交换排序如下所述 1 第一趟对序列中所有奇数项i扫描 将a i 和a i 1 进行比较 2 第二趟对序列中所有偶数项i扫描 将a i 和a i 1 进行比较 3 每次比较时若 a i gt a i 1 则将两者交换 4 第三趟对所有
  • 读取excel文件转为HTML

    最近写了一个公式较复杂的报表 因梳理公式与后期的数据核对会比较耗费时间 因此采用了读取EXCEL模板 然后填写数据 最后读取最终文件生成页面的方法 现整理了将EXCEL转为HTML的方法 本人在用的xlsx文件 颜色不支持灰色 建议使用其他
  • el-date-picker日期限定范围

    el date picker日期限定范围 页面
  • 一文看懂RPA的技术架构及原理

    一文看懂RPA的技术架构及原理 众所周知 作为一款软件或平台 RPA 机器人流程自动化 是用来替代人类员工实施基于规则的高度重复性工作的程序 而非实体存在的流程处理机器 但由于它的新颖性 许多人可能会对RPA及其构成感到困惑 典型的RPA平
  • VS 2015 新建QT项目

    打开VS 2015 文件 新建 新建项目 选择QT5 Projects QT Application 没有出现上述菜单的 请重新安装Visual Studio Add in 1 2 4 for Qt5 并重启VS QT创建向导 选择必要组件
  • 分布式服务高可用实现:复制

    1 为什么需要复制 我们可以考虑如下问题 当数据量 读取或写入负载已经超过了当前服务器的处理能力 如何实现负载均衡 希望在单台服务器出现故障时仍能继续工作 这该如何实现 当服务的用户遍布全球 并希望他们访问服务时不会有较大的延迟 怎么才能统
  • Java异常学习总结

    1 什么是异常 异常本质上是程序上的错误 包括程序逻辑错误和系统错误 在Java中异常被当做对象来处理 根类是java lang Throwable类 在Java中定义了很多异常类 如OutOfMemoryError NullPointer