当前位置: 首页 > news >正文

【一步一步了解Java系列】:认识异常类

看到这句话的时候证明:此刻你我都在努力
加油陌生人
微信图片编辑_20240229212205.png

个人主页:Gu Gu Study
专栏:一步一步了解Java

喜欢的一句话: 常常会回顾努力的自己,所以要为自己的努力留下足迹


喜欢的话可以点个赞谢谢了。
作者:小闭


异常类的概念及其层次结构

Java中存在异常类,那么何为异常类呢?那么我们必须先了解一下它的概念:Java异常处理是Java语言中非常重要的一部分,它允许程序在遇到错误时能够优雅地处理问题而不是直接崩溃。Java异常类主要分为两大类:检查型异常(Checked Exceptions)和非检查型异常(Unchecked Exceptions)。

  1. 检查型异常/编译时异常(Checked Exceptions)
    • 这些异常通常是由于编程错误导致的,比如FileNotFoundException或SQLException。
    • 它们必须在方法签名中声明抛出,或者在方法内部被处理(通常是通过try-catch块)。
    • 在运行前编译器就已经报出警告了:
    • image.png
  2. 非检查型异常/运行时异常(Unchecked Exceptions)
    • 这些异常通常是由于运行时错误导致的,比如NullPointerException或ArithmeticException。
    • 它们不需要在方法签名中声明,也不强制要求必须被捕获处理。
    • 如图在运行前编译器是不会提示错误的:image.png

Java中的异常就像我们生活中人生病一样,我们的程序也会生病,我们可以把计算机的病就叫做“异常”。


那么下面就给大家解析一下其层次结构:
Java异常类的层次结构从__java.lang__包中的__Throwable__类开始,它有两个主要的子类:Exception__和__Error

  • Throwable:
    • Java异常类的根类。
    • 有两个重要的子类:Exception和Error。
  • Exception:
    • 表示程序本身可以处理的异常情况。
    • 进一步分为IOException、SQLException等。
  • RuntimeException:
    • Exception的一个子类,表示在Java程序运行时发生的异常。
    • 包括NullPointerException、IndexOutOfBoundsException等。
  • Error:
    • 表示JVM无法处理的错误,比如OutOfMemoryError或StackOverflowError。
    • 通常不需要程序去捕获这些错误

有关处理异常的关键词

在Java中处理异常我们有这么几个常用的关键词 :throw、try、catch、finally、throws。

  1. ** throw 抛出异常 **

如下是一个简单的异常抛出,我们在一个方法中要执行一条语句时,如果其可能会发生异常,如:null,分母为0,数组访问越界,我们都可以自己抛出异常,如下为一个空指针异常

package demo1;public class Test {public static void testExceptinon(int[] arr){if(arr==null){throw new ArithmeticException();}}public static void main(String[] args) {int[] arr=null;testExceptinon(arr);}}

image.png
所谓抛出异常其实就是抛出一个Exception或Exception的子类。
注意事项:

抛出异常类其必须是Exception或Exception的子类。
抛出异常必须在方法内部
如果抛出的是 RunTimeException 或者 RunTimeException 的子类,则可以不用处理,直接交给JVM来处理
** 如果抛出的是编译时异常,用户必须处理,否则无法通过编译**
** 异常一旦抛出,其后的代码就不会执**


  1. 异常声明throws

throws一个用来声明异常的关键词,是用在方法上的,具体格式为
** 修饰符 返回值类型 方法名(参数列表) throws 异常类型1,异常类型2…{ } **
注意throws只是起到警示作用,就是给程序员知道用这个方法可能会抛出异常。不会解决异常。

public class Test {public static final void test1 ()throws RuntimeException{int a=10;int c=0;System.out.println(a/c);}}
  1. ** try-catch捕获并处理 **

解决异常还得用到try-catch语句,这是我们常用处理异常的关键词,当然还有finally关键词,稍后我也会提到。

import com.sun.security.jgss.GSSUtil;public class Test {public static final void test1 ()throws ArithmeticException{int a=10;int c=0;System.out.println(a/c);}public static void main(String[] args) {int q=10;int p=100;String s="hello world";System.out.println(q+p);try{test1();              //try的花括号内是放入可能会抛出异常的语句//如果里面的语句没有抛出异常则会跳出try-catch语句}catch (ArithmeticException e){   //小括号里是放入可能会捕捉到的异常类 eSystem.out.println("处理异常");  //catch花括号内是我们自行处理异常的方法}finally {System.out.println("无论是否捕捉到异常都一定会执行的代码");   //finally里的语句无论是否检测到异常都会执行的语句}System.out.println("处理完异常后的代码执行");  //这是处理异常后才会执行的语句// 当异常被捕获到时,异常就被处理了,这里的后序代码一定会执行//如果捕获了,由于捕获时类型不对,那就没有捕获到,这里的代码就不会被执行}}
  1. try的花括号内是放入可能会抛出异常的语句, 如果里面的语句没有抛出异常则会跳出try-catch语句
  2. catch的小括号里是放入可能会捕捉到的异常类 e,catch花括号内是我们自行处理异常的方法
  3. catch-catch-finally外的语句:当异常被捕获到时,异常就被处理了,这里的后序代码一定会执行,如果捕获了,由于捕获时类型不对,那就没有捕获到,这里的代码就不会被执行

  1. ** finally **

配合try-catch语句用的,但是其不是一定要加上去的,而try-catch一定是一起出现的。
在写程序时,有些特定的代码,不论程序是否发生异常,都需要执行,比如程序中打开的资源:网络连接、数据库 连接、IO流等,在程序正常或者异常退出时,必须要对资源进进行回收。另外,因为异常会引发程序的跳转,可能 导致有些语句执行不到,finally就是用来解决这个问题的。

public static int getData() {Scanner sc = null;try {sc = new Scanner(System.in);int data = sc.nextInt();return data;} catch (InputMismatchException e) {e.printStackTrace();} finally {System.out.println("finally中代码");}System.out.println("try-catch-finally之后代码");if (null != sc) {sc.close();}return 0;
}public static void main(String[] args) {int data = getData();System.out.println(data);
}

上述程序,如果正常输入,成功接收输入后程序就返回了,try-catch-finally之后的代码根本就没有执行,即输入流 就没有被释放,造成资源泄漏。


自定义异常类

使用的较多的异常类往往是我们自己定义的比较多,那么如何自定义异常类呢,下面我们就来讲讲如何自定义异常类。

class textException extends RuntimeException{public textException() {}public textException(String message) {super(message);}
}public class Test1 {public static void main(String[] args) {int a=0;if(a==0){throw new textException();}}}

image.png
如上我们只需让自己创建出的类继承Exception或其它异常类即可,这样这个类也是一个异常类了。
然后我们在需要抛出异常时,抛出自己定义的异常即可。
也可以用try-catch进行使用解决自己定义的异常。
注意事项:

  • ** 自定义异常通常会继承自 Exception 或者 RuntimeException **
  • **继承自 Exception 的异常默认是受查异常 **
  • **继承自 RuntimeException 的异常默认是非受查异常 **

异常的处理流程

关于 “调用栈” 方法之间是存在相互调用关系的, 这种调用关系我们可以用 “调用栈” 来描述. 在 JVM 中有一块内存空间称为 “虚拟机栈” 专门存储方法之间的调用关系. 当代码中出现异常的时候, 我们就可以使用 e.printStackTrace(); 的 方式查看出现异常代码的调用栈. 如果本方法中没有合适的处理异常的方式, **就会沿着调用栈向上传递 **

public class Test {public static final void func1(){int[] a={1,2,3,4,5};a[10] = 100;}public static void main(String[] args) {try {func1();System.out.println("hello world");}catch (ArrayIndexOutOfBoundsException e){e.printStackTrace();System.out.println("没能合适解决异常");}}
}

image.png
如上图:在func1中如果没进行处理,堆栈就会延栈调用,也就是图中又看mian方法中是否能够处理好异常,一直向上传递如果都无法解决,一旦交给JVM处理那么程序将会终止,就不会进行之后的代码。

异常类与if的区别

首先我们来说说if在应对程序的应用是怎样的?
if语句:
比如:下面代码我们的if就是在检测到b==0时,就不让程序继续进行下面的计算。
这属于一种事先防卫型,就是避免错误发生。在发生之前就将程序阻断。

package demo1;import java.util.Scanner;public class Test {public static void main(String[] args) {Scanner sc=new Scanner(System.in);int a=sc.nextInt();int b=sc.nextInt();if(b==0){System.out.println("分母为0,数字不合法");}else {System.out.println("a/c= "+a/b);}}
}

异常类:
如下:异常类相比于if更像是先斩后奏型,事后处理型,在程序发现问题时在进行处理问题,如下代码将可能有异常的语句放到try括号中,如果出现异常在进行解决:

package demo1;public class Test1 {public static void main(String[] args) {int a=10;int b=0;try{System.out.println("a/c= "+a/b);}catch (ArithmeticException e){System.out.println("捕捉到异常并解决异常的方法");}}
}

相关文章:

  • Redis学习|Redis 是什么、Redis 能干嘛、Window安装Redis、Linux下安装Redis、Redis测试性能
  • 2023-2024山东大学移动互联网开发期末回忆
  • 6.22面试问题【1】长链表排序选择归并还是快排
  • 动手学深度学习(Pytorch版)代码实践 -卷积神经网络-14模型构造
  • 在C#中对 JSON进行序列化和反序列化处理
  • 物联网协议应用
  • 【GO-OpenCV】go-cv快速配置
  • Spring的自动注入(也称为自动装配)
  • 分享excel全套教程速成,高效人士的Excel必修课,附视频课程!
  • 基于SpringBoot+Vue在线考试报名系统设计和实现(源码+LW+调试文档+讲解等)
  • 【SCAU数据挖掘】数据挖掘期末总复习题库简答题及解析——下
  • 使用 DISPATCHERS 进行 Blueprint 之间的通信
  • Python二级考试试题
  • Python高效内存访问,memoryview这个神器你值得拥有!
  • zlib库的交叉编译记录
  • 【跃迁之路】【669天】程序员高效学习方法论探索系列(实验阶段426-2018.12.13)...
  • 2019.2.20 c++ 知识梳理
  • js算法-归并排序(merge_sort)
  • JS题目及答案整理
  • storm drpc实例
  • VirtualBox 安装过程中出现 Running VMs found 错误的解决过程
  • vue 个人积累(使用工具,组件)
  • 半理解系列--Promise的进化史
  • 从重复到重用
  • 第三十一到第三十三天:我是精明的小卖家(一)
  • 紧急通知:《观止-微软》请在经管柜购买!
  • 前端攻城师
  • 世界编程语言排行榜2008年06月(ActionScript 挺进20强)
  • 视频flv转mp4最快的几种方法(就是不用格式工厂)
  • 一起参Ember.js讨论、问答社区。
  • 智能合约Solidity教程-事件和日志(一)
  • PostgreSQL之连接数修改
  • ​520就是要宠粉,你的心头书我买单
  • ​如何使用ArcGIS Pro制作渐变河流效果
  • # Maven错误Error executing Maven
  • # 数据结构
  • #NOIP 2014# day.1 生活大爆炸版 石头剪刀布
  • #pragma once与条件编译
  • #鸿蒙生态创新中心#揭幕仪式在深圳湾科技生态园举行
  • (2024,LoRA,全量微调,低秩,强正则化,缓解遗忘,多样性)LoRA 学习更少,遗忘更少
  • (2024.6.23)最新版MAVEN的安装和配置教程(超详细)
  • (AtCoder Beginner Contest 340) -- F - S = 1 -- 题解
  • (第8天)保姆级 PL/SQL Developer 安装与配置
  • (分布式缓存)Redis分片集群
  • (深入.Net平台的软件系统分层开发).第一章.上机练习.20170424
  • (一)Thymeleaf用法——Thymeleaf简介
  • (一)WLAN定义和基本架构转
  • (原創) X61用戶,小心你的上蓋!! (NB) (ThinkPad) (X61)
  • (转)用.Net的File控件上传文件的解决方案
  • **Java有哪些悲观锁的实现_乐观锁、悲观锁、Redis分布式锁和Zookeeper分布式锁的实现以及流程原理...
  • ..回顾17,展望18
  • .bat批处理(九):替换带有等号=的字符串的子串
  • .NET Project Open Day(2011.11.13)
  • .netcore 获取appsettings
  • .net中的Queue和Stack