Java异常梳理总结

目录

什么是异常 , 异常的分类 ?

异常的基本概念

什么是Throwable ?

Throwable 类常用方法有哪些?

Exception 和 Error 有什么区别?

运行时异常与一般异常有什么区别?

常见的RuntimeException 有哪些 ?

NoClassDefFoundError 和 ClassNotFoundException 有什么区别?

举一个例子什么时候会出现NoClassDefFoundError

什么是自定义异常,如何使用自定义异常 ?

异常处理

Java异常处理的方式?

Java异常处理相关的几个关键字

throw 和 throws 两个关键字的区别吗

try-catch-finally 一系列问题

try-catch-finally 如何使用?

如何使用 try-with-resources 代替try-catch-finally?

try-with-resources的原理(todo)

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

try-catch-finally 中哪个部分可以省略?

try-catch-finally中,如果 catch中return了,finally还会执行吗?

使用异常注意事项

异常使用有哪些需要注意的地方

java try-catch 捕获异常真的会影响性能吗?

异常处理相关代码题

参考


什么是异常 , 异常的分类 ?

当程序发生不正确的行为,就代表程序出现了问题 这就代表发生了异常.

异常有很多类型,我们会将异常进行分类

Throwable是 Java 语言中所有错误或异常的基类

Throwable 又分为Error和Exception,其中

  • ErrorError 属于程序无法处理的错误 ,我们没办法通过 catch 来进行捕获不建议通过catch捕获 。例如 Java 虚拟机运行错误(Virtual MachineError)、虚拟机内存不够错误(OutOfMemoryError)、类定义错误(NoClassDefFoundError)等 。这些异常发生时,Java 虚拟机(JVM)一般会选择线程终止。
  • Exception是程序问题导致的异常 , 可以通过 catch 来进行捕获,又分为两种:
    • CheckedException 受检异常:编译器会强制检查并要求处理的异常。比如 IOexception,classNotFoundException
    • RuntimeException 运行时异常:程序运行中出现异常,比如我们熟悉的空指针、数组下标越界等等

异常的基本概念

什么是Throwable ?

public class Throwable implements Serializable {}

Throwable是异常最顶级的异常类,他有两个重要的子类分别是

  • error
  • exception

这两个子类也分别包含了许多子类

Throwable 类常用方法有哪些?

  • String getMessage(): 获取异常信息
  • String toString(): 返回详细信息 ,包括获取异常类名和异常信息
  • void printStackTrace(): 异常的堆栈跟踪信息 , 在控制台上打印异常类名和异常信息,以及异常出现在程序中的位置
  • getStackTrace(): 返回一个堆栈跟踪元素数组,每个元素代表一个方法调用,通过 getStackTrace() 方法,我们可以打印异常发生的位置,并追踪调用了哪些方法,这在调试和定位问题时非常有用。
try{int a = 10 / 0;
}catch (Throwable throwable) {System.out.println(throwable.toString());// 返回异常的详细信息,包括异常名字+异常信息System.out.println(throwable.getMessage());// 返回异常信息System.out.println(throwable.getStackTrace());// 返回堆栈信息throwable.printStackTrace(); // 打印堆栈信息
}

Exception 和 Error 有什么区别?

在 Java 中,所有的异常都有一个共同的祖先 java.lang 包中的 Throwable 类。Throwable 类有两个重要的子类:

  • Exception : 程序本身可以处理的异常,可以通过 catch 来进行捕获。程序设计的不完善而出现的问题,程序必须处理的问题, Exception 又可以分为 Checked Exception (受检查异常,必须处理) 和 Unchecked Exception (不受检查异常,可以不处理)。
  • ErrorError 属于系统级别的错误,Java运行环境内部错误或者硬件问题,并不指望程序处理这样的问题,除了退出别无选择 ,它是由Java虚拟机抛出的。例如 Java 虚拟机运行错误(Virtual MachineError)、虚拟机内存不够错误(OutOfMemoryError)、类定义错误(NoClassDefFoundError),栈溢出(StackOverFlowError)等 。这些异常发生时,Java 虚拟机(JVM)一般会选择线程终止。

运行时异常与一般异常有什么区别?

首先Exception就代表程序出现了问题, 分为 运行时异常和一般异常

一般异常 : 编译器强制需要我们进行显式处理这种异常. 否则无法编译通过,这是一种强制的规范 .比如IOException,ClassNotfoundException

需要我们进行捕获或者向上抛出.

就比如FileNotFoundException(表示文件不存在)这个异常,目的就是告诉这个方法的调用者,这个方法并不一定可以成功,是有可能找不到文件的,所以就要对这种情况做出特殊的处理.

所以当我们希望我们的方法调用者,明确的处理一些特殊情况的时候,就应该使用受查异常.

运行时异常 : 是因为代码错误导致的,程序在运行的时候出现了问题.编译器并不强制让我们处理这种异常, 比如 空指针异常,数组越界异常, 算术异常等; 运行时异常无需显式捕获或声明,编译器不会强制要求我们处理这些异常。

这样的异常,我们一般可以理解为由于代码原因导致的,比如空指针,数组越界等. 所以只要代码写的没有问题,这些异常都是可以避免的,不需要我们显示的处理

常见的RuntimeException 有哪些 ?

  • 空指针异常
  • 非法参数异常
  • 类型转换异常
  • 算术异常
  • 数组越界异常
  • 字符串下标越界异常

此异常由 String 方法抛出,指示索引或者为负,或者超出字符串的大小。

  • 数组存储异常
  • 数字格式化异常
  • 并发修改异常

RuntimeException 及其子类都统称为非受检查/运行时异常,常见的有 :

  • NullPointerException(空指针异常):当对一个对象引用调用实例方法、访问实例字段时,对象引用为null时抛出该异常。
  • IllegalArgumentException(非法参数异常):当传递给一个方法的参数无效或不合法时抛出该异常。
 Date date = new Date("2022-09-10");
  • IndexOutOfBoundsException(索引越界异常):当访问数组、集合或字符串的索引超出范围时抛出该异常。
  • ArithmeticException(算术异常):当进行数学运算出现错误时抛出该异常,例如除以零。
  • ClassCastException(类转换异常):当尝试将一个对象转换成不兼容的类型时抛出该异常。
Object object = new String("Hello");
Integer number = (Integer) object; // 尝试将字符串转换为整数
  • NumberFormatException(数字格式化异常 字符串转换为数字格式错误,IllegalArgumentException的子类)
// 我们尝试将一个非数字字符串 "abc123" 解析为整数。由于该字符串不符合整数的格式,
// 因此无法将其解析为整数.在这种情况下,会抛出 NumberFormatException 异常。
int l = Integer.valueOf("sffff");
  • ConcurrentModificationException(并发修改异常):当在使用迭代器遍历集合时,集合的结构被修改而导致的异常。
int abc = Integer.parseInt("abc");
System.out.println(abc);
  • ArrayStoreException 试图将错误类型的对象存储到一个对象数组时抛出的异常。
 public static void main(String[] args) {Object x[] = new String[3];x[0] = new Integer(0);
}

NoClassDefFoundError 和 ClassNotFoundException 有什么区别?

首先都是由于运行时找不到要加载的类导致的,有一些区别

总结一下两者的区别:

  1. NoClassDefFoundError是运行时错误 ,是发生在运行时找不到类导致的,ClassNotFoundException是编译时异常(checked 异常,需要显式处理),在编译时无法找到类导致的(这个类在类路径中没有被找到)
  2. NoClassDefFoundError通常是在编译的时候,类存在,运行时不存在 可能是因为该类从运行时的类路径中移除或者没有添加, 缺少jar文件 .jar包出现损坏或者篡改.  ClassNotFoundException通常是由代码中显式调用了不存在的类或导入了错误的类名导致的。可以检查代码中的类名是否拼写正确、是否导入了正确的类等

举一个例子什么时候会出现NoClassDefFoundError

当出现NoClassDefFoundError时,意味着某个在编译时存在的类在运行时无法找到。以下是一个简单的例子来说明NoClassDefFoundError的情况:

假设我们有两个Java类:MainClass和HelperClass。MainClass依赖于HelperClass,而HelperClass在编译时存在,但在运行时无法找到。

MainClass.java:

public class MainClass {public static void main(String[] args) {HelperClass helper = new HelperClass();helper.doSomething();}
}

HelperClass.java:

public class HelperClass {public void doSomething() {System.out.println("Doing something...");}
}

在编译时,这两个类被正确编译为MainClass.class和HelperClass.class。然而,如果在运行时只提供MainClass.class文件,而缺少了HelperClass.class文件,那么当运行MainClass时,就会抛出NoClassDefFoundError。

可以通过以下步骤来模拟并触发NoClassDefFoundError异常:

  1. 将HelperClass.class从运行时的类路径中移除,只保留MainClass.class。
  2. 使用命令行或IDE来运行MainClass。

运行时,将会抛出类似以下的NoClassDefFoundError错误:

Exception in thread "main" java.lang.NoClassDefFoundError: HelperClassat MainClass.main(MainClass.java:4)Caused by: java.lang.ClassNotFoundException: HelperClassat java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583)at java.base/jdk.internal.loader.ClassLoaders\$AppClassLoader.loadClass(ClassLoaders.java:178)at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)... 1 more

这表明虚拟机无法找到HelperClass类,并且导致NoClassDefFoundError异常的抛出。

要解决这个问题,可以确保在运行时的类路径中包含所有必需的类文件,并正确配置依赖关系。

什么是自定义异常,如何使用自定义异常 ?

自定义异常就是开发人员自己定义的异常,一般可以通过继承Exception的子类的方式来实现.

编写自定义异常实际上是继承一个API标准异常类,用新定义的异常处理信息覆盖原有信息的过程.

这种用法在Web开发中还比较常见,一般用来自定义业务异常,如余额不足,重复提交等,这种自定义异常有业务含义,更容易让上层理解和处理.

异常处理

Java异常处理的方式?

异常处理方式主要是有2种方式 :

  1. 自己进行处理,使用try catch进行捕获
  2. 向上抛出异常,让调用者来处理

如果自己知道是如何处理,那么自己就捕获异常进行处理. 否则就向上抛,让调用者来处理.

向上抛出异常主要有两个关键字 :

加在方法上 : throws 异常类

方法体中 : throw 异常对象

     3. 对于SpringBoot项目来说我们还可以通过异常处理器来进行捕获项目中出现的异常,也就是如果项目中有异常就抛异常就可以, 最终都会被异常处理器锁捕获到,然后进行统一的异常处理.

Java异常处理相关的几个关键字

try , catch , finnaly , throw , throws

try : 我们可以把可能出现异常的代码放到try块中

catch : 使用catch捕获可能发生的异常,如果捕获了,可以对异常进行处理

finaly : 不管代码执行发生了什么,我们都要执行的一段代码可以放在finally块中

throws 加在方法上 throws 异常类,异常类......

throw 在方法体内部, throw 异常对象

throw 和 throws 两个关键字的区别吗

  • throws 加载方法上,表示这个方法可能抛出的异常,可以声明多个异常类
  • throw 适用于在方法体上抛异常, throw后面跟对象,只能是一个异常对象.

try-catch-finally 一系列问题

try-catch-finally 如何使用?
  • try 关键字后面会跟一个大括号 {} , 我们把一些可能发生异常的代码放到大括号里
  • try 块后面一般会跟 catch 块,用来处理发生异常的情况

当 try 块中的某一行代码发生异常时,之后的代码就不再执行,而是会跳转到异常对应的 catch 块中,catch 用来捕获不同类型的异常并做相应的处理,如果一个 try 块后面跟了多个与之关联的 catch 块,那么应该把特定的异常放在前面,通用型的异常放在后面,不然编译器会提示错误

  • 异常不一定会发生,为了保证发不发生异常都能执行一些代码,就会跟一个 finally 块。
  • finally 块不是必选项,有 try 块的时候不一定要有 finally 块。但是有finally块时前面必须有 try 块. 如果 finally 块中的代码可能会发生异常,也应该使用 try-catch 进行包裹。
  • 即便是 try 块中执行了 return、break、continue 这些跳转语句,finally 块也会被执行。

但finaly也不一定执行

  • 遇到了死循环。
  • 执行了 System. exit() 这行代码。
如何使用 try-with-resources 代替try-catch-finally?

面对必须要关闭的资源,我们总是应该优先使用 try-with-resources 而不是try-finally。代码更简短,更清晰,产生的异常对我们也更有用。try-with-resources语句让我们更容易编写必须要关闭的资源的代码.

  • 使用try-with-resources 就是在try后面加上个括号,资源都放在括号中,这样就会自动关闭资源.

使用try-finally容易导致丢失异常堆栈信息,使得我们无法正确的定位异常信息.

而用try-with-resources 就可以避免这种情况.

try-with-resources的原理(todo)

try-with-resources语句能够确保每一个资源在语句结束时被关闭,但是有一个前提条件,那就是这个资源必须实现Java.Lang.AutoCloseable or java.io.Closeable 接口,才可以被执行.

try语句中越是最后使用的资源,越是最早被关闭的. 并且还用了addSuppressed/方法,确保不会丢失任何异常.

为 Throwable 类新增了 addSuppressed 方法,支持将一个异常附加到另一个异常身上,从而避免异常屏蔽。

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

finally块在Java中通常用于处理善后工作,如释放资源。

通常情况下, 如果在try块被执行并且程序正常的运行,那么finally块的内容一定会被执行.

否则finally块就不一定执行.

比如, 如下情况 :

  • 我们直接kill 杀死掉进程
  • 在try或者catch中发生了死循环
  • 虚拟机发生了崩溃
  • 程序遇到无法恢复的错误,如OutOfMemoryError
  • 调用System.exit()方法

System.exit()方法用于终止当前运行的Java虚拟机。一旦Java虚拟机被终止,任何后续的代码,包括finally块,都不会被执行。

try-catch-finally 中哪个部分可以省略?

当想要使用try-catch-finally的时候,有几种组合

  • try-catch
  • try-finally
  • try-多个catch捕获异常-finally

可以省略catch或者finally。catch和finally不可以同时省略。

try-catch-finally中,如果 catch中return了,finally还会执行吗?

trycatch块中有return语句,finally块仍然会执行, 如果finally块中也有return语句,那么它将覆盖trycatch块中的任何return语句,成为方法的最终返回值。

使用异常注意事项

异常使用有哪些需要注意的地方

  • 不要把异常定义为静态变量,这样可能会让堆栈信息错乱.我们应该每次都new一个异常对象抛出

因为可能发生,每一次抛出异常,都会覆盖静态变量中存储的先前异常信息

  • 抛出的异常信息要更加详细
  • 抛出的异常类要更加具体, 比如是算术异常,我们就抛出算术异常信息,类型转换异常我们就抛出异常转换异常,而不是为了省事,抛出Exception
  • 使用日志打印异常之后就不要再抛出异常了(两者不要同时存在一段代码逻辑中)。

java try-catch 捕获异常真的会影响性能吗?

异常处理相关代码题

参考

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

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

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

相关文章

面试总结之JVM入门

文章目录 🐒个人主页🏅JavaEE系列专栏📖前言:🎀你为什么要学习JVM?🎀JVM的作用 🎀JVM的构成(5大类)🏨1.类加载系统🐕类什么时候会被加…

《业务建模驱动的企业架构转型白皮书》

当前,我国金融等国民经济重点行业和企业的数字化转型,仍存在战略落地难、业务技术协同难以及投入产出匹配难等问题,亟需通过实施企业架构,从顶层设计出发,制定符合自身需要的转型战略;从全局视角出发&#…

人工智能产生的幻觉问题真的能被看作是创造力的另一种表现形式吗?

OpenAI的首席执行官山姆奥特曼(Sam Altman)曾声称,人工智能产生的“幻觉”其实未尝不是一件好事,因为实际上GPT的优势正在于其非凡的创造力。 目录 一.幻觉问题的概念 二.幻觉产生的原因 三.幻觉的分类 四.减轻AI的幻觉问题到…

Windows部署WebDAV服务并映射到本地盘符实现公网访问本地存储文件

文章目录 前言1. 安装IIS必要WebDav组件2. 客户端测试3. 使用cpolar内网穿透,将WebDav服务暴露在公网3.1 安装cpolar内网穿透3.2 配置WebDav公网访问地址 4. 映射本地盘符访问 前言 在Windows上如何搭建WebDav,并且结合cpolar的内网穿透工具实现在公网访…

Qt QWidget 简约美观的加载动画 第四季

&#x1f60a; 第四季来啦 &#x1f60a; 效果如下: 只有三个文件,可以直接编译运行的 //main.cpp #include "LoadingAnimWidget.h" #include <QApplication> #include <QVBoxLayout> #include <QGridLayout> int main(int argc, char *argv[]) …

matlab 三质量-弹簧系统受激振力

1、内容简介 略 44-可以交流、咨询、答疑 建立系统运动方程&#xff0c;研究固有频率和对应主振型 2、内容说明 略 三质量&#xff0d;弹簧系统受激振力&#xff0c;并不考虑各自的阻尼。建立系统运动方程。 解&#xff1a;由于阻尼对固有频率没有影响&#xff0c;故本文不…

【蓝桥杯省赛真题25】python密室逃脱游戏 青少年组蓝桥杯比赛python编程省赛真题解析

目录 python密室逃脱游戏 一、题目要求 1、编程实现 2、输入输出

【深入理解设计模式】代理设计模式

代理设计模式&#xff1a; 代理设计模式是一种结构型设计模式&#xff0c;它允许你提供一个替代物或占位符来控制对其他对象的访问。在代理模式中&#xff0c;一个类代表另一个类的功能。这种类型的设计模式属于结构型模式&#xff0c;因为该模式涉及类和对象的组合。 概述 …

常见集合框架底层原理

常见集合框架底层原理 常见的集合有哪些 Java集合类主要由两个接口Collection和Map派生出来的&#xff0c;Collection有三个子接口: List、 Set、Queue List代表了有序可重复集合&#xff0c;可直接根据元素的索引来访问Set代表了无序集合&#xff0c;只能根据元素本身来访问…

代码随想录算法训练营第62天 | 739.每日温度 496.下一个更大元素I

每日温度 如果我们单纯的遍历数组&#xff0c;我们不知道当前元素是否比之前的元素大&#xff0c;所以需要维护一个容器来记录遍历过的元素。 什么时候用单调栈&#xff1f;通常是一维数组&#xff0c;要寻找任一个元素的右边或左边第一个比自己大或小的元素的位置。时间复杂度…

Linux-实用操作(黑马学习笔记)

各类小技巧&#xff08;快捷键&#xff09; ctrl c 强制停止 ● Linux某些程序的运行&#xff0c;如果想要强制停止它&#xff0c;可以使用快捷键ctrl c ● 命令输入错误&#xff0c;也可以通过快捷键ctrl c&#xff0c;退出当前输入&#xff0c;重新输入 ctrl d 退出或登…

客户端订阅服务端事件的机制

一、场景描述 产业大脑平台是一个典型的审核系统&#xff0c;用户发布到平台的信息需要经过审核员审核后生效。 用户发布信息->审核员审核信息->用户信息生效&#xff0c;这一流程可能发生在用户的同一次登录周期内。为了使客户端能实时响应信息的状态变化&#xff0c;…

使用Node.js和Vue.js构建全栈Web应用

随着互联网的迅速发展&#xff0c;Web应用程序的开发变得越来越复杂和多样化。为了满足用户不断变化的需求&#xff0c;全栈开发已成为一个备受关注的话题。在本篇博客中&#xff0c;我将介绍如何使用Node.js和Vue.js来构建全栈Web应用。 Node.js是一个基于Chrome V8引擎的Jav…

AI之T2I:Stable Diffusion 3的简介、安装和使用方法、案例应用之详细攻略

AI之T2I&#xff1a;Stable Diffusion 3的简介、安装和使用方法、案例应用之详细攻略 目录 Stable Diffusion 3的简介 1、效果测试 官方demo 网友提供 Stable Diffusion 3的安装和使用方法 1、安装 2、使用方法 Stable Diffusion 3的案例应用 1、基础案例 Stable Diff…

庖丁解牛-二叉树的遍历

庖丁解牛-二叉树的遍历 〇、前言 01 文章内容 一般提到二叉树的遍历&#xff0c;我们是在说 前序遍历、中序遍历、后序遍历和层序遍历 或者说三序遍历层序遍历&#xff0c;毕竟三序和层序的遍历逻辑相差比较大下面讨论三序遍历的递归方法、非递归方法和非递归迭代的统一方法然…

数据结构2月25日

第一道&#xff1a; 第二道&#xff1a; 1、插入到prev和next中间 1.new(struct list_head*)malloc(sizeof(struct list_head*)); if(newNULL) { printf("失败\n"); return; } new->nextprev->next; prev->nextnew; return; 2、删除prve和next…

Mybatis-Plus学习

文章目录 一、简介1. 概述2. 特点3. 框架架构 二、入门案例1. 数据库环境准备2. SpringBoot工程准备3. 配置application.yml4. 项目开发5. MybatisPlus测试 三、BaseMapper1. 源码2. 方法测试 四、IService1. 简介2. 使用IService3. 测试IService 五、MybatisPlus为我们提供的一…

大文件传输之udp如何传输大量数据

在数字化时代&#xff0c;对大文件传输的需求正以前所未有的速度增长。无论是个人用户还是企业&#xff0c;都急切寻求一种能够快速且稳定地处理大量数据的传输方法。UDP&#xff08;用户数据报协议&#xff09;以其无连接的特性和高效的数据传输能力&#xff0c;成为了大文件传…

啤酒:探索精酿啤酒与家常菜的温馨滋味

在繁忙的生活中&#xff0c;我们总是在寻找一种简单而温馨的美食享受。家常菜&#xff0c;作为最具代表性的传统美食&#xff0c;以其丰富的口味和深厚的情感价值而受到广泛欢迎。而当Fendi Club啤酒遇上家常菜&#xff0c;它们将共同演绎出一曲充满温情的味觉交响曲。 Fendi C…