面试突击:深入理解 Java 中的异常

本文已收录于:https://github.com/danmuking/all-in-one(持续更新)

前言

哈喽,大家好,我是 DanMu。今天想和大家聊聊 Java 中的异常。异常处理是一种重要的概念,因为程序总是会出现各种意料之外的问题:有可能是逻辑错误,也可能某位小可爱想看一个练习了 null 年半的练习生跳舞,程序不可能永远正确运行。但是,我们也希望程序在出错之后可以继续运行,不能影响正常用户的使用。因此,我们需要一种机制,保证程序能够在出错后进行一定程度的处理后继续运行。

Java 异常概览:

先来看看 Java 中的异常体系异常.drawio.png

Throwable

在 Java 中,所有的异常相关类都继承于一个父类,java.lang 包中的 Throwable 类。

public class Throwable implements Serializable

Throwable 中比较重要的方法有:

  • String getMessage(): 返回异常发生时的简要描述
  • String toString(): 返回异常发生时的详细信息
  • String getLocalizedMessage(): 返回异常对象的本地化信息。使用 Throwable 的子类覆盖这个方法,可以生成本地化信息。如果子类没有覆盖该方法,则该方法返回的信息与 getMessage()返回的结果相同
  • void printStackTrace(): 在控制台上打印 Throwable 对象封装的异常信息

Exception 和 Error

Throwable 有两个重要的子类,Exception 和 Error:
从字面含义来说,Exception 翻译为异常,Error 翻译为错误,显然 Error 代表这更加严重的问题,在使用中也同样如此。
Error:
Error 属于程序无法处理的错误 ,不建议通过 catch 捕获 。例如 Java 虚拟机运行错误(Virtual MachineError)、虚拟机内存不够错误(OutOfMemoryError)、类定义错误(NoClassDefFoundError)等 。这些异常发生时,Java 虚拟机(JVM)一般会选择线程终止。
Exception:
程序本身可以处理的异常,可以通过 catch 来进行捕获。Exception 又可以分为 Checked Exception (受检查异常,必须处理) 和 Unchecked Exception (不受检查异常,可以不处理)。

由于 Error 通常不建议进行处理,所以在代码编写中,我们更多接触的通常是 Exception。

Checked Exception(受检异常)和 Unchecked Exception(非受检异常)?

Checked Exception
Checked Exception受检查异常 ,Java 代码在编译过程中,如果受检查异常没有被 catch 或者 throws 关键字处理的话,就没办法通过编译。
比如这个简单的例子:
image.png
除了 RuntimeException 及其子类以外,其他的 Exception 类及其子类都属于受检查异常 。常见的受检查异常有:IO 相关的异常、ClassNotFoundException、SQLException…。
Unchecked Exception
Unchecked Exception不受检查异常 ,Java 代码在编译过程中 ,我们**即使不处理不受检查异常也可以正常通过编译。**这类异常通常与到程序运行时的状态有关。Unchecked Exception 主要包括 RuntimeException 及其子类,常见的有

  • NullPointerException(空指针错误)
  • IllegalArgumentException(参数错误比如方法入参类型错误)
  • NumberFormatException(字符串转换为数字格式错误,IllegalArgumentException的子类)
  • ArrayIndexOutOfBoundsException(数组越界错误)
  • ClassCastException(类型转换错误)
  • ArithmeticException(算术错误)
  • ……

建议大家根据需要记上 3-4 个,面试的时候如果问到能适当的举出几个例子。

image.png

try-catch-finally 和 try-with-resources

try-catch-finally

try-catch-finally 由 3 部分组成

  • try:用于捕获异常其后可接零个或多个 catch 块,如果没有 catch 块,则必须跟一个 finally 块。
  • catch:用于处理 try 捕获到的异常。
  • finally:**无论是否捕获或处理异常,finally 块里的语句都会被执行。**当在 try 块或 catch 块中遇到 return 语句时,finally 语句块将在方法返回之前被执行。

这是一个简单的例子:

public static void main(String[] args) {
    try {
      int[] myNumbers = {1, 2, 3};
      System.out.println(myNumbers[10]);
    } catch (Exception e) {
      System.out.println("Something went wrong.");
    } finally {
      System.out.println("The 'try catch' is finished.");
    }
  }

注意:不要在 finally 语句块中使用 return! 当 try 语句和 finally 语句中都有 return 语句时,try 语句块中的 return 语句会被忽略。这是因为 try 语句中的 return 返回值会先被暂存在一个本地变量中,当执行到 finally 语句中的 return 之后,这个本地变量的值就变为了 finally 语句中的 return 返回值。

finally 中的代码一定会执行吗?

不一定!在某些情况下,finally 中的代码不会被执行。
就比如说 finally 之前虚拟机被终止运行的话,finally 中的代码就不会被执行。

try {
    System.out.println("Try to do something");
    throw new RuntimeException("RuntimeException");
} catch (Exception e) {
    System.out.println("Catch Exception -> " + e.getMessage());
    // 终止当前正在运行的Java虚拟机
    System.exit(1);
} finally {
    System.out.println("Finally");
}

输出:

Try to do something
Catch Exception -> RuntimeException

另外,在以下 2 种特殊情况下,finally 块的代码也不会被执行:

  1. 程序所在的线程死亡。
  2. 强制关闭 CPU。

虽然在实际应用中很难遇到这样子的场景,但是在面试时不少面试官还是很喜欢问这类问题,所以还是要稍微注意一下

try-with-resources

在 Java 中,所有被打开的系统资源,比如流、文件或者Socket连接等,都需要被开发者手动关闭,否则随着程序的不断运行,资源泄露将会累积成重大的生产事故。但是每一个打开的资源都伴随着一个需要被处理的异常,如果一次性需要打开多个资源,那异常的处理就会变成一场噩梦,比如这个例子:

public class Demo {
    public static void main(String[] args) {
        BufferedInputStream bin = null;
        BufferedOutputStream bout = null;
        try {
            bin = new BufferedInputStream(new FileInputStream(new File("test.txt")));
            bout = new BufferedOutputStream(new FileOutputStream(new File("out.txt")));
            int b;
            while ((b = bin.read()) != -1) {
                bout.write(b);
            }
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            if (bin != null) {
                try {
                    bin.close();
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
                finally {
                    if (bout != null) {
                        try {
                            bout.close();
                        }
                        catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }
}

Fxxk!我只是想要读写两个文件,异常处理的代码竟然比业务代码长的多!这是因为,我们不仅需要关闭 BufferedInputStream ,还需要保证如果关闭 BufferedInputStream 时出现了异常, BufferedOutputStream 也要能被正确地关闭。所以我们不得不借助 finally 中嵌套 finally 大法。可以想到,打开的资源越多,finally 中嵌套的将会越深!
为了释放程序员的双手,在 1.7 中 Java 新增了一个 try-with-resources 语法糖,我们重新改写一下上面的例子

public class TryWithResource {
    public static void main(String[] args) {
        try (BufferedInputStream bin = new BufferedInputStream(new FileInputStream(new File("test.txt")));
             BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream(new File("out.txt")))) {
            int b;
            while ((b = bin.read()) != -1) {
                bout.write(b);
            }
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }
}

只需要将要打开的资源放在try后的()中,不同资源间用;分割,就可以自动完成资源的关闭。代码一下子就清爽了!try-with-resources 虽好但是也有几点需要注意

  1. 适用范围(资源的定义): 任何实现 java.lang.AutoCloseable或者 java.io.Closeable 的对象
  2. 关闭资源和 finally 块的执行顺序: 在 try-with-resources 语句中,任何 catch 或 finally 块在声明的资源关闭后运行

点关注,不迷路

好了,以上就是这篇文章的全部内容了,如果你能看到这里,非常感谢你的支持!
如果你觉得这篇文章写的还不错, 求点赞👍 求关注❤️ 求分享👥 对暖男我来说真的 非常有用!!!
白嫖不好,创作不易,各位的支持和认可,就是我创作的最大动力,我们下篇文章见!
如果本篇博客有任何错误,请批评指教,不胜感激 !

最后推荐我的IM项目DiTing(https://github.com/danmuking/DiTing-Go),致力于成为一个初学者友好、易于上手的 IM 解决方案,希望能给你的学习、面试带来一点帮助,如果人才你喜欢,给个Star⭐叭!

参考资料

Java基础常见面试题总结(下)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/732900.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

代码签名证书有什么作用?有哪些申请步骤?

代码签名证书是一种数字证书,它为软件开发者提供一种验证软件代码真实性和完整性的方法。通过使用代码签名证书,开发者可以确保他们的软件在发布后没有被篡改,并且用户可以信任软件的来源。 什么是代码签名证书? 代码签名证书是提…

同三维高清大屏多功能一体机简介——高清多能数字矩阵

产品简介 同三维高清多能数字矩阵(硬件集软件于一体)是依据当前高清视频正广泛应用于各类项目工程的整体形势而专门研发的、特点显著、优势诸多、极具创新性的专业级一体化监控产品。高清多能数字矩阵采用WINDOWS操作系统,基于高性能配置的刀…

换电脑后导入git本地仓库记录

导入本地仓库tig记录 换了新电脑,将旧电脑的数据盘查到新的笔记本之后发现,使用pycharm 读取不到本地的git提交记录了,我没有将本地git上传到远程仓库的习惯,这可抓马了,硬盘插回去的话也太麻烦了。试了 vscode 提示设…

【英伟达GPU的挑战者】Groq—AI大模型推理的革命者

目录 引言第一部分:Groq简介第二部分:Groq的特点与优势1、高性能推理加速2、近存计算技术3、专用ASIC芯片设计4、低延迟与高吞吐量5、成本效益分析6、易用性与集成性7、软件与硬件的协同设计 第三部分:Groq的使用指南1、准备工作2、简单使用样…

通过 Setapp 使用 240 多款 Mac 生产力工具以及 GPT-4o

Setapp 是一项革命性的订阅服务,可以使用 240 多款 Mac 应用程序的综合套件,并配有强大的人工智能助手。 通过 Setapp 为你的工作效率和生产力增添魔力。 Setapp 官网:访问(提供 7 天试用) Setapp 的主要功能 AI 助手…

高通安卓12-Input子系统

1.Input输入子系统架构 Input Driver(Input设备驱动层)->Input core(输入子系统核心层)->Event handler(事件处理层)->User space(用户空间) 2.getevent获取Input事件的用法 getevent 指令用于获取android系统中 input 输入事件,比如获取按键上报信息、获…

黑马苍穹外卖3 菜品管理 AOP+反射+阿里云OSS+基本增删改查

菜品管理 公共字段自动填充 对员工,菜品,套餐、、的设置时间等,导致代码冗余。 使用切面来为这些方法统一设置 枚举:标识当前操作的类型(不同来类型操作的字段名不同)。反射(为公共字段赋值&a…

大模型自然语言生成自动驾驶可编辑仿真场景(其一 共十篇)

第一篇:LLM greater scene summarize 第二篇:LLM simulation Test effect 第三篇:LLM simulation driving scenario flow work 第四篇:LLM Algorithm flow description 第五篇:Configure the environment and back…

k8s离线部署nginx

1. 拉取nginx离线包到本地 sudo docker save nginx:latest -o nginx.tar 2. 导入nginx image到k8s命名空间中 sudo ctr -n k8s.io images import nginx.tar 3. 编辑nginx.yaml apiVersion: apps/v1 kind: Deployment metadata:name: nginx-deployment spec:selector:match…

yocto系列讲解[实战篇]94 - 添加libhybris库和测试示例

By: fulinux E-mail: fulinux@sina.com Blog: https://blog.csdn.net/fulinus 喜欢的盆友欢迎点赞和订阅! 你的喜欢就是我写作的动力! 目录 1. 概述2. 添加libhybris的recipe3.libhybris编译4.libhybris测试5.自制Android C++动态库6.自制Android C++动态库编译7.创建testhyb…

java基于ssm+jsp 高校二手交易平台

1前台首页功能模块 高校二手交易平台,在系统首页可以查看首页、商品信息、论坛信息、新闻资讯、我的、跳转到后台、客服等内容,如图1所示。 图1系统功能界面图 用户登录、用户注册,在注册页面可以填写账号、密码、姓名、手机、身份证等信息进…

故障诊断 | SABO-VMD-SVM轴承故障诊断(Matlab)

效果一览 文章概述 故障诊断 | SABO-VMD-SVM轴承故障诊断(Matlab) 模型描述 减法平均的优化算法(Subtraction-Average-Based Optimizer (SABO)),是于2023年提出的一种基于数学行为的智能优化算法,该算法具有寻优能力强,收敛速度快等特点。以最小包络熵、最小样本熵、最…

2024GLEE生活暨教育(上海)博览会,8月20-22日,国家会展中心(上海)

2024GLEE生活暨教育(上海)博览会将于8月20-22日在中国国家会展中心(上海)举行,博览会总面积近万平方米,设有美好生活和教育产品两大主力展区,全面覆盖婴幼儿、学龄前、小学、初中、高中、大学、中年、老年各个年龄段的…

机械师硬盘数据清空怎么办?机械师硬盘数据清空怎么恢复

机械师硬盘数据清空怎么恢复?随着数字化时代的到来,数据已成为我们生活和工作中不可或缺的一部分。然而,硬盘数据的意外清空往往会给我们带来极大的困扰。本文将探讨在机械师硬盘数据清空后,我们应该如何快速有效地恢复数据。 图片…

软件开发教学:在线教育系统源码解析及教育培训小程序搭建实战

本篇文章,笔者将以“从零开始的软件开发教学”为主题,详细解析在线教育系统的源码,并通过实际操作来搭建一个教育培训小程序。 一、在线教育系统概述 在线教育系统是一个综合性的网络平台,旨在通过互联网提供教育资源和服务。该系…

Docker开机自动重启及自动启动容器

Docker开机自动重启及自动启动容器 Windows开机自动重启设置容器自动启动 Windows开机自动重启 勾选 Start Docker Desktop when you sign in to your computer 设置容器自动启动 1.docker update 命令 Usage: docker update [OPTIONS] CONTAINER [CONTAINER...]Update co…

“迷你剧场新体验:探索短剧小程序系统的魅力!“

在移动互联网的时代背景下,短视频和短剧已经成为人们娱乐消费的新宠。短剧小程序系统,以其独特的互动形式、便捷的观看体验和丰富的内容生态,为迷你剧场带来了全新的体验。接下来将探讨这个系统的魅力所在,以及它如何改变着人们的…

plt绘制网格图

代码 obj "accu" for (epoch,lr) in config:with open(data/epoch_{}_lr_{}_Adam.pkl.format(epoch,lr),rb) as f:data pickle.load(f) plt.plot(range(1,epoch1),data[obj],labelflr{lr})plt.title(obj"-epoch") plt.xlabel("epoch"…

AMSR/ADEOS-II L1A Raw Observation Counts V003地球表面和大气微波辐射的详细观测数据

AMSR/ADEOS-II L1A Raw Observation Counts V003 简介 AMSR/ADEOS-II L1A Raw Observation Counts V003数据是由日本航空航天研究开发机构(JAXA)的AMSR (Advanced Microwave Scanning Radiometer)仪器收集的一组原始观测计数数据。这些数据是从ADEOS-I…

ARM阻击高通:AI PC大战与芯片之争

引言 在AI PC领域,高通的X Elite芯片因为其高性能和低功耗,一度被认为是未来的主导者。然而,ARM公司却通过法律手段试图阻止高通的独大,这不仅可能拖慢AI PC的发展进程,还引发了业界的广泛关注。本文将深入探讨ARM和高…