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

news2024/11/28 12:39:31

本文已收录于: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基础常见面试题总结(下)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

分享计算机msvcp100.dll,丢失或找不到的7个解决方法

msvcp100.dll是动态链接库文件对于执行使用 Microsoft Visual C 2010 编译器编译的应用程序至关重要。它包含了 C 标准库的实现,提供了应用程序运行时所需的核心功能,如输入/输出操作、字符串处理、数学运算和异常处理等。若系统中缺失或损坏此文件&…

win10环境配置ollama-ui运行llama3模型

先说我的笔记本电脑配置intel-i7-11390h,4核8处理器,内存16G。显卡NVIDA GeFroce MX450,2G显存,这是一台5000元左右的电脑。 我用它跑roop、sd1.5、ffusion2、ChatTTs还有pythonpytorch的自定义模型,现在用来跑llama3。当然&…

挑战Midjourney,融合近百个SD大模型的通用模型AlbedoBase XL

在SDXL的通用模型中,DreamShaperXL和juggernautXL这2款大模型一直都深受广大AI绘画者的喜爱,不可否认,这2款通用模型在很多方面表现都相当出色。 今天再给大家介绍一款基于SDXL的通用大模型:AlbedoBase XL,作者的目标…

Centos7 Mysql8.3.0 安装地址

MySQL :: Download MySQL Community Server (Archived Versions)

qt 5.6 qmake手册

qt 5.6 qmake手册 (笔者翻译的qmake手册,多数是机翻,欢迎评论区纠错修正) Qmake工具有助于简化跨不同平台开发项目的构建过程。它自动生成Makefile,因此创建每个Makefile只需要几行信息。您可以将qmake用于任何软件项目…

解决 执行 jar 命令 控制台乱码

Springboot项目,编码为utf8 打包后,为了在控制台运行时不乱码,需要在控制台中依次执行以下命令: 第一步: chcp 65001第二步: java -jar -Dfile.encodingutf-8 你的.jar

使用 GitOps 进行防灾 MinIO

想象一下,您已经花费了无数小时来完善 Docker Swarm 设置,精心设计每项服务,并调整 CI/CD 管道以实现无缝自动化。现在,想象一下这个经过微调的系统被重置为原点,不是因为严重的故障或安全漏洞,而是因为数据…

windows下mysql修改 my.ini的datadir后 `Access denied`

1. 背景 window安装mysql数据库时,不能指定数据文件存放位置(默认安装路径 "C:/ProgramData")。 只能通过修改mysql.ini来更改数据文件存放目录。 2. 问题: 修改mysql.ini后,mysql 出现 "Access denied for user ‘root‘@‘localhost‘ (using passwor…

如何清除anaconda3缓存?

如果长期使用anaconda不清理缓存,会导致anaconda占用磁盘空间越来越多,甚至系统磁盘撑爆。 清除包缓存: 打开 Anaconda Prompt 或者命令行窗口。运行以下命令清除包缓存:conda clean --all这会清除所有的包缓存,释放磁…

调试实战 | 记一次有教益的 vs2022 内存分配失败崩溃分析(续)

前言 前一阵子遇到了 vs2022 卡死的问题,在上一篇文章中重点分析了崩溃的原因 —— 当 vs2022 尝试分配 923MB 的内存时,物理内存页文件大小不足以满足这次分配请求,于是抛出异常。 本篇文章将重点挖掘一下 vs2022 在崩溃之前已经分配的内容…

关于使用绿联 USB-A转RJ45 2.5G网卡提速的解决问题

问题 网络下载速率低 网线是七类网线,外接的USB网卡驱动 我的自带网卡是 I219v 在嵌入了2.5G网络后一直无法到达1.5G以上。 平均测速300~500M 解决方案 更新了USB的网卡驱动 禁用了 I219-V的驱动。测速即可 USB驱动下载地址 https://download.csdn.net/downlo…

2024 年值得考虑的 5 款 PDF 转换器

您可以使用名为PDF 转换器(可移植文档格式)的软件应用程序将数据从一种格式转换为另一种格式,具体来说就是转换为 PDF 格式或从 PDF 格式转换为 PDF 格式。由于无论使用什么程序或平台查看,PDF 格式的格式和布局都保持不变&#x…

教育培训机构寒暑假班学校公众号小程序

📚教育培训学校公众号版本:开启学习新纪元🚀 一、引言:为何教育培训学校需要公众号版本? 随着数字化时代的来临,传统教育培训行业也在不断探索新的服务模式。公众号作为新媒体平台的一种,具有信…

网络安全知识全景地图V1.0 - 20240616更新

网络安全领域的知识全景涵盖了从基础概念到高级技术的广泛内容。博主基于自身十年多的工作经验结合CISSP认证官方教材按照不同的主题和层次梳理出如下高层次的概览地图,可以帮助个人和组织理解网络安全领域的主题。 1.1. 基础理论 1.1.1. 网络安全概述 网络安全的…

反激开关电源输出电解电容选型及计算

电容高频模型:ESRESLC的串联 1、耐压:根据输出的电压来取,需留一定余量,比如5V输出可以选6.3V或者10V的电解电容 2、容量 纹波电压 电容充放电引起的纹波电压(与电容容量存在着直接因果关系) ESR引起的纹…

哎呦我, HashMap KeySet有序? 好像是哈

背景:有8个格子,上架物品时需要从第一个格子开始上架,不能跳格子,也就是说 如果格子1空着,就不能把物品放到格子2。有这么个顺序的情况 前人模块功能实现: 用HashMap 初始化格子信息,然后用 Ke…

Docker:centos79-docker-compose安装记录

1.安装环境:centos7.9 x86 2.安装最新版: [rootlocalhost ~]# curl -fsSL get.docker.com -o get-docker.sh [rootlocalhost ~]# sh get-docker.sh # Executing docker install script, commit: e5543d473431b782227f8908005543bb4389b8desh -c yum in…

STM32硬件接口I2C应用(基于FT6336)

目录 概述 1 硬件介绍 1.1 ST7796-LCD 1.2 MCU IO与LCD PIN对应关系 1.3 MCU IO与Touch PIN对应关系 2 FT6336的寄存器 2.1 FT6336寄存器列表 2.2 寄存器功能介绍 3 STM32Cube控制配置I2C 3.1 软硬件版本信息 3.2 I2C参数配置 3.3 使用STM32Cube产生工程 4 HAL库…

深入了解RTMP推流技术:视频汇聚EasyCVR低延迟与高稳定性分析

RTMP(Real Time Messaging Protocol)视频推流技术,作为音视频传输领域的关键技术之一,已经在直播、视频会议、在线教育等多个场景中得到了广泛应用。RTMP以其独特的优势,为实时音视频传输提供了高效、稳定的解决方案。…

前端路线指导(4):前端春招秋招经验分享

春招/秋招经验分享(前端) 哈喽大家好,我是小粉,双一流本科,自学前端一年,收获腾讯,字节等多家大厂offer,一半以上ssp~ 今天给大家分享一下我的春招(暑期实习)、秋招经历,…