【Java】全面解析异常(异常的分类、处理、抛出和捕获等)

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: “程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常。”

什么是异常

“程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常。”

我们在平时写代码的过程中就可能会遇到异常,给大家给举一些容易遇到常见的异常例子:

1.算术异常

10.png

Exception in thread “main” java.lang.ArithmeticException: / by zero

在JAVA中,我们都知道0不能作为除数,只能作为被除数,如果把0作为除数,编译器就会提示我们出先算术异常了。

2.数组越界异常

11.png

Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: 5

数组越界,我们应该也不陌生,在使用数组时,如果超过了数组的大小,就会形成越界。程序就会发生异常,从而终止运行。

3.空指针异常

12.png

Exception in thread “main” java.lang.NullPointerException

对于数组arr,让它赋值为null,我并没有让它指向任何对象,它就是一个空指针。对于空指针进行访问,编译器就会提示我们空指针异常。


异常的分类


在代码运行时,可能会出现异常种类有很多,为了对不同异常或者错误进行很好的分类管理,Java内部维护了一个异常的体系结构:

13.png

图画的不是很好,大家凑合着看吧。下面为大家讲解一下这张图:

1.Throwable类是Java语言中所有错误(errors)和异常(exceptions)的父类。

2.Error:指的是Java虚拟机无法解决的严重问题,比如:JVM的内部错误、资源耗尽等。

3. Exception:异常产生后程序员可以通过代码进行处理,使程序继续执行。

异常可能在编译时发生,也可能在程序运行时发生,根据发生的时机不同,可以将异常分为运行时异常和编译时异常。

编译时异常

编译时异常,也称为受检查异常。从名字我们就能够理解,就是程序在编译的时候发生的异常。

运行时异常

在程序执行期间发生的异常,称为运行时异常,也称为非受检查异常。

编译时出现的语法性错误,不能称之为异常。编译过程中就会出错, 这是 “编译期” 出错。而运行时指的是程序已经编译通过得到class 文件了,再由 JVM 执行过程中出现的错误.

在Java中,异常处理主要的5个关键字:throw、try、catch、finally、throws

在讲异常处理之前,我们先要了解一下异常处理中的关键字,接下来我会一一为大家介绍这些关键字。


异常的抛出(throw关键字)


在Java中,可以借助throw关键字,抛出一个指定的异常对象,将错误信息告知给调用者

使用方法:throw new XXXException(“异常产生的原因”);

例如:

public static void main(String[] args) {

           throw new RuntimeException();

       }

14.png

虽然代码没错,但是我是使用throw抛出的一个异常,所以程序就会反馈给我一个异常。

给大家总结一下throw在使用过程中要注意的一些地方:

throw必须写在方法体内部

抛出的对象必须是Exception 或者 Exception 的子类对象

如果抛出的是 RunTimeException 或者 RunTimeException 的子类,则可以不用处理,直接交给JVM来处理

如果抛出的是编译时异常,用户必须处理,否则无法通过编译

异常一旦抛出,其后的代码就不会执行

异常的捕获


异常的捕获,就是异常的具体处理方式,主要有两种:异常声明throws 和try-catch捕获然后进行处理。

throws关键字

throws一般位于方法声明时参数列表之后。

使用方法:修饰符 返回值 方法名(形参)throws 异常类型(可以有多个异常类型)

声明的异常必须是 Exception 或者 Exception 的子类

如果有多个异常,有用逗号隔开,如果抛出的异常具有父子类关系,可以直接throws父类

但是不建议直接用throws父类,范围太大了。throws对异常并没有真正处理,而是将异常报告给抛出异常方法的调用者,由调用者处理。如果要处理异常就要使用try-catch进行处理。

try、catch关键字

使用方式如下所示:

public static void main(String[] args) {

           try{

               //代码

           }catch (){//()里面写你想捕捉的异常

               //处理异常的代码

           }catch (){

   //同上

           }

       }

1.try里面的代码不一定会发生异常。

2. 如果代码发生了异常,且被catch捕获到了,就会进行对应的处理,处理完成后就会跳出try-catch执行后面的语句。

3.如果代码发生了异常,但不是写catch语句预期捕捉的异常的话,那么这个异常不会捕捉到,后面的代码就不会被执行。

4.try-catch可以捕捉多个异常,但不是同时捕获。如果有多个异常,只能逐个捕获。

5.如果有多个异常,并且有父子类关系,可以直接写Exception,因为它是所有异常的父类,但是也不建议这么写,因为Exception的范围太广了,因为每个异常处理的方法不一样。

6.如果使用Exception,那么在写catch的时候,要么只写一个catch语句,里面放Exception,后面就不能继续写catch语句了,因为写了也没什么用,而且出现的异常都会被Exception进行捕获。要么就把Exception放在最后写,前面写你想捕获的异常,在最后再使用Exception。

7. try里面抛出异常位置之后的代码将不会被执行


finally关键字


finally的使用很简单,使用方式如下:

public static void main(String[] args) {

           try{

               //代码

           }catch (RuntimeException e){

               //()里面写你想捕捉的异常

               //处理异常的代码

           }catch (Exception e){

   //同上

           } finally{

         //代码

        }

   }

finally的作用:finally后面的代码一定会执行

前面讲了try-catch用来捕获并处理异常,但是有时发生的异常并没有被捕捉到,那么程序也会发生异常终止,但用户在使用的时候发生异常并终止程序,我们也需要对此进行进行一定的处理,就可以使用finally关键字,无论有没有发生异常,finally内的代码也一定会执行。


自定义异常


具体方式:

自定义异常类,然后继承自Exception 或者 RunTimeException

实现一个带有String类型参数的构造方法,参数含义:出现异常的原因

案例:

如果我们要实现一个登录账号的功能,在用户名或者密码错误时能够提示我们一下.而这个时候我们就可以使用自定义异常来解决这个问题.

分析:因为是登陆问题的异常,所以命名为LoginException,登陆时提醒我们,就是运行时异常,因此要继承RunTimeException 并实现RunTimeException里面带有String类型参数的构造方法.

可以实现的构造方法一共有这些,实现第二个即可

16.png

  public static void main(String[] args) {

       String userName1 = "admin";

       String password1 = "123456";

       Scanner scanner =  new Scanner(System.in);

       System.out.print("请输入用户名:");

       String userName2 = scanner.next();

       System.out.print("请输入密码:");

       String password2 = scanner.next();

       if (!userName1.equals(userName2)){

           throw new LoginException("用户名错误!");

       }

       if (!password1.equals(password2)){

           throw new LoginException("密码错误!");

       }

       System.out.println("登录成功!");

   }

自定义异常:

public class LoginException extends RuntimeException{

   public LoginException(String message) {

       super(message);

   }

}

运行结果:

17.png21.png

22.png

自定义异常通常会继承自 Exception 或者 RuntimeException

继承自 Exception 的异常默认是受查异常

继承自 RuntimeException 的异常默认是非受查异常


总结


异常处理的流程

程序先执行 try 中的代码

如果 try 中的代码出现异常, 就会结束 try 中的代码, 看和 catch 中的异常类型是否匹配.

如果找到匹配的异常类型, 就会执行 catch 中的代码

如果没有找到匹配的异常类型, 异常得不到处理,就会交给JVM处理,程序就会异常终止.

无论是否找到匹配的异常类型, finally 中的代码都会被执行到(在该方法结束之前执行).

相关文章
|
9天前
|
人工智能 自然语言处理 Java
FastExcel:开源的 JAVA 解析 Excel 工具,集成 AI 通过自然语言处理 Excel 文件,完全兼容 EasyExcel
FastExcel 是一款基于 Java 的高性能 Excel 处理工具,专注于优化大规模数据处理,提供简洁易用的 API 和流式操作能力,支持从 EasyExcel 无缝迁移。
65 9
FastExcel:开源的 JAVA 解析 Excel 工具,集成 AI 通过自然语言处理 Excel 文件,完全兼容 EasyExcel
|
16天前
|
存储 缓存 Java
Java 并发编程——volatile 关键字解析
本文介绍了Java线程中的`volatile`关键字及其与`synchronized`锁的区别。`volatile`保证了变量的可见性和一定的有序性,但不能保证原子性。它通过内存屏障实现,避免指令重排序,确保线程间数据一致。相比`synchronized`,`volatile`性能更优,适用于简单状态标记和某些特定场景,如单例模式中的双重检查锁定。文中还解释了Java内存模型的基本概念,包括主内存、工作内存及并发编程中的原子性、可见性和有序性。
Java 并发编程——volatile 关键字解析
|
5天前
|
JSON 供应链 搜索推荐
淘宝APP分类API接口:开发、运用与收益全解析
淘宝APP作为国内领先的购物平台,拥有丰富的商品资源和庞大的用户群体。分类API接口是实现商品分类管理、查询及个性化推荐的关键工具。通过开发和使用该接口,商家可以构建分类树、进行商品查询与搜索、提供个性化推荐,从而提高销售额、增加商品曝光、提升用户体验并降低运营成本。此外,它还能帮助拓展业务范围,满足用户的多样化需求,推动电商业务的发展和创新。
23 5
|
6天前
|
API 数据处理 开发者
获取淘宝分类详情:深入解析taobao.cat_get API接口
淘宝开放平台推出的`taobao.cat_get` API接口,帮助开发者和商家获取淘宝、天猫的商品分类详情。该接口支持获取类目列表、属性及父类目信息,通过指定分类ID(cid)实现精准查询,并提供灵活的参数设置和高效的数据处理。使用流程包括注册账号、创建应用、获取App Key/Secret、构造请求、发送并解析响应。示例代码展示了如何用Python调用此API。开发者可借此为电商项目提供数据支持。
|
14天前
|
Java 数据库连接 Spring
反射-----浅解析(Java)
在java中,我们可以通过反射机制,知道任何一个类的成员变量(成员属性)和成员方法,也可以堆任何一个对象,调用这个对象的任何属性和方法,更进一步我们还可以修改部分信息和。
|
1月前
|
存储 算法 Java
Java内存管理深度解析####
本文深入探讨了Java虚拟机(JVM)中的内存分配与垃圾回收机制,揭示了其高效管理内存的奥秘。文章首先概述了JVM内存模型,随后详细阐述了堆、栈、方法区等关键区域的作用及管理策略。在垃圾回收部分,重点介绍了标记-清除、复制算法、标记-整理等多种回收算法的工作原理及其适用场景,并通过实际案例分析了不同GC策略对应用性能的影响。对于开发者而言,理解这些原理有助于编写出更加高效、稳定的Java应用程序。 ####
|
1月前
|
存储 监控 算法
Java虚拟机(JVM)垃圾回收机制深度解析与优化策略####
本文旨在深入探讨Java虚拟机(JVM)的垃圾回收机制,揭示其工作原理、常见算法及参数调优方法。通过剖析垃圾回收的生命周期、内存区域划分以及GC日志分析,为开发者提供一套实用的JVM垃圾回收优化指南,助力提升Java应用的性能与稳定性。 ####
|
2月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
93 2
|
15天前
|
存储 设计模式 算法
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。 行为型模式分为: • 模板方法模式 • 策略模式 • 命令模式 • 职责链模式 • 状态模式 • 观察者模式 • 中介者模式 • 迭代器模式 • 访问者模式 • 备忘录模式 • 解释器模式
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
|
15天前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。 结构型模式分为以下 7 种: • 代理模式 • 适配器模式 • 装饰者模式 • 桥接模式 • 外观模式 • 组合模式 • 享元模式
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析

热门文章

最新文章

推荐镜像

更多