Java---认识异常

欢迎大家来观看本博课------Java------认识异常。1.异常的概念和体系结构

1.异常的概念和体系结构 

1.1 异常的概念

在Java中,在程序执行过程中发生的不正常行为称为异常。如在之前我们经常遇到的算数异常(ArithmeticException)、数组越界异常(ArrayIndexOutOfBoundsException)和空指针异常(NullPointerException )。

1.2 异常的体系结构

在Java中,异常是一种类。由于异常的种类太多了,为了对异常和错误进行很好的分类管理,Java内部维护了一个异常的体系结构。

如下图

从上图可以看出异常的种类众多

1. Throwable位于最高层,是所有异常和错误的父类,派生出了Exception和Error两个子类。

2. Error是指Java虚拟机无法解决的严重问题。

3. Exception是指程序在发生不正常行为后,程序员可以通过调整代码,是程序正常运行。

1.3 异常的分类

异常分为两种,分别为编译时异常和运行时异常。

1.编译时异常

编译时异常也被称为受检查异常。即程序没运行时,编译器就会划红线报异常。

以我们之前讲的克隆为例子

如上图,程序都还没运行,编译器就会划红线报异常了,这就是编译时异常。

2.运行时异常

 运行时异常也被称为不受查异常,即在程序运行之后才会出现的异常。

如以上代码,程序运行前没有出现任何异常,但是运行代码后,就会报出下图的异常。这就是所谓的运行时异常。 

2. 异常的处理

 在Java中,关于异常的处理我们要用带5个关键字,分别为throw,try,catch,finally和throws

1. 异常的抛出----throw

public class Test {private static void func(int a){if(a==0){throw new ArithmeticException();}}public static void main(String[] args) {func(0);}
}

运行以上代码

public class Test {private static void func(int a){if(a==0){throw new ArithmeticException("a==0");}}public static void main(String[] args) {func(0);}
}

 以上个代码的区别在哪呢?就是一个抛出的异常传了参数,一个没有传参数。

这个传递的字符串通常是产生异常的原因。如果传来参数,运行的时候,字符串也会显示出来。

【注意事项】

1. throw必须写在方法的内部。

2.throw抛出的异常需要是Exception类或者是Exception的子类。

3.如果throw抛出的异常是运行时异常,可以不写,最后交给JVM来处理。

4.如果throw抛出的是编译时异常,则程序员必须处理,否则程序无法运行。

5.throw一但抛出,后续代码将不会运行。

6.throw抛出的一般是自定义异常。(软性要求)

2.异常的捕获

异常的捕获,也就是异常的处理方式。通常是异常声明---throws关键字和异常捕获try-catch两种。

1.异常声明---throws关键字

异常申明一般处于方法的参数列表的后面,如果程序不想亲自解决该方法声明的异常,我们可以将该异常抛给方法的调用者来处理。即当前的方法不处理异常,让方法的调用来处理异常

以之前实现对象的克隆为例子:

之前我们实现克隆的时候为什么到这一步还会保错呢?

因为我们在调用clone这个方法的时候,这个clone方法声明了一个异常,需要该方法的调用者来处理这个异常。明显是在main方法中调用了该clone方法,所以main方法要来处理这个异常。处理方式就是也在方法的调用者的方法参数列表后面在声明一次该异常就行了。

如下图

【注意事项】

1.throws的异常声明只能写在函数参数列表的后面。

2.throws声明的异常必须是Exception类或者Exception的子类。

3.如果方法内部抛出了多个异常,throws后面就得写多个异常,中间用逗号隔开。如果异常的类型之间存在父子类的关系,则只声明也可以。  

2.异常的捕获并处理----try{...}catch(...){...}

throws声明的异常并没有对异常进行真正的处理,如果想真正得对异常进行处理,需要用到try和catch关键字。

语法格式

try{...
}catch(){...
}

代码演示

public static void func(){int[] arr={1,2,3};System.out.println(arr[4]);}public static void main(String[] args) {try{func();}catch (ArrayIndexOutOfBoundsException e){System.out.println("捕获数组越界异常");e.printStackTrace();}}

从上面代码,我们知道func()方法里面出现了数组越界的异常,我们将出现异常的代码放在try的代码块里面,接着在catch的括号里面写上对应出现的异常。

【注意事项】

1.try...catch中可以根多种异常,知道与catch后的异常类型匹配为止。

public static void func(){int[] arr={1,2,3};System.out.println(arr[4]);}public static void main(String[] args) {try{func();}catch (NullPointerException e){System.out.println("捕获了空指针异常");e.printStackTrace();}catch (ArithmeticException e){System.out.println("捕获了算术异常");e.printStackTrace();}catch (ArrayIndexOutOfBoundsException e){System.out.println("捕获数组越界异常");e.printStackTrace();}}

如上面的代码,虽然也写了catch很多异常,但是抛出的异常是数组越界异常,所以只会执行与数组越界异常匹配的catch语句。

 2.如果try里面的代码块里的代码出现了异常,那么try代码块就不会执行出现异常代码之后的代码但如果try代码块里面不出现异常,则try代码块里面的所有代码都会执行。

public static void func(){int[] arr={1,2,3};System.out.println(arr[4]);}public static void main(String[] args) {try{func();System.out.println("func()后面的代码");}catch (ArrayIndexOutOfBoundsException e){System.out.println("捕获数组越界异常");e.printStackTrace();}}

由于func()抛出了异常,所以就不会执行try代码块里面func()后面的代码。

3. 只有捕捉到了异常,catch代码块里面的的代码才会运行。

public static void main(String[] args) {try{int n=10;}catch (ArrayIndexOutOfBoundsException e){System.out.println("捕获数组越界异常");e.printStackTrace();}}

 由于try代码快里面的代码没有出现异常,则catch就没有捕获异常,则catch代码快里面的代码就不会运行。

4.如果try代码块里面抛出了多个异常,只会捕捉一个异常,因为当捕捉了一个代码之后,代码就会终止了。

3.finally关键字

在程序运行的时候,会有一些特定的代码,不管程序是否抛出异常,都需要执行。比如程序资源的打开:网络连接、数据库连接和IO流。在程序正常运行或者出现异常时,必须实现对资源的关闭,否则会造成内存泄漏。另外,可能因为程序抛出异常,会导致一些代码执行不了。这时候就要用到finally关键字。因为finally代码块里面不管前面的代码是否抛出异常,finally代码块里面的代码都会执行。

1. 程序抛出异常

public static void main(String[] args) {int[] arr={1,2,3};try{arr[4]=0;}catch (ArrayIndexOutOfBoundsException e){System.out.println("捕获到数组越界异常");}finally {System.out.println("finally代码块运行");}}

运行代码 

 2. 程序不抛出异常

public static void main(String[] args) {int[] arr={1,2,3};try{arr[2]=0;}catch (ArrayIndexOutOfBoundsException e){System.out.println("捕获到数组越界异常");}finally {System.out.println("finally代码块运行");}}

 3. 易错点

public static int func(){try{return 20;}catch (ArrayIndexOutOfBoundsException e){System.out.println("捕获到数组越界异常");}finally {return 100;}}public static void main(String[] args) {int data= func();System.out.println(data);//打印100}

之所以最后的结果是100,我们可以理解为因为finally代码块终究会执行,所以程序就会只执行finally代码块里面的return语句。 

 4. 异常处理总结

首先会执行try代码块里面的代码,看其是否抛出异常。如果抛出异常,就会看catch代码块有没有匹配的异常,如果catch边没有找到对应的异常,就会交给上层调用者去处理。如果上层调用者也没有处理异常,则会交给main方法处理,如果main方法也没有处理,则最后就会交给JVM去处理。

3.自定义异常类

虽然在Java中,异常的种类也很丰富了,但终会有一些异常在Java中是没有定义的,所以我们要学会自定义异常类。

1. 自定义异常一般都会继承Exception类或者RunTimeException类。

2. 继承Exception类是受检查类。

3. 继承RunTimeException类是不受检查类。

实现登录异常

自定义NameExcetion类继承Exception

public class NameException extends Exception{public NameException() {super();}public NameException(String message) {super(message);}
}

自定义Password类继承RuntimeException

public class PasswordException extends RuntimeException{public PasswordException() {super();}public PasswordException(String message) {super(message);}
}

主函数

class Login {public String password;public String name;public Login(String password, String name) {this.password = password;this.name = name;}public  void login(String password,String name)throws PasswordException,NameException{if(!this.password.equals(password)){throw new PasswordException("密码错误");}if(!this.name.equals(name)){throw new NameException("用户名错误");}System.out.println("登录成功");}
}
public class Test {public static void main(String[] args) {Login login=new Login("123","man");try{login.login("123","man");}catch (PasswordException e){e.printStackTrace();}catch (NameException e){e.printStackTrace();}}
}

我们也可以在login函数处理继承Exception类抛出的异常。

class Login {public String password;public String name;public Login(String password, String name) {this.password = password;this.name = name;}public  void login(String password,String name){if(!this.password.equals(password)){throw new PasswordException("密码错误");}try {if(!this.name.equals(name)){throw new NameException("用户名错误");}}catch (NameException e){e.printStackTrace();}System.out.println("登录成功");}
}
public class Test {public static void main(String[] args) {Login login=new Login("123","man");try{login.login("123","man");}catch (PasswordException e){e.printStackTrace();}}
}

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

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

相关文章

数据结构学习笔记-并查集

“查”操作&#xff1a;确定一个指定元素所属集合。 “并”操作&#xff1a;将两个不相交的集合并为一个。 1.用双亲表示法实现并查集 #define SIZE 13 int UFSets[SIZE]; //集合元素数组//初始化并查集 void Initial(int S[]){for(int i0;i<SIZE;i)S[i]-1; }//Find &…

GDB:从零开始入门GDB

目录 1.前言 2.开启项目报错 3.GDB的进入和退出 4.GDB调试中查看代码和切换文件 5.GDB调试中程序的启动和main函数传参 6.GDB中断点相关的操作 7.GDB中的调试输出指令 8.GDB中自动输出值指令 9.GDB中的调试指令 前言 在日常开发中&#xff0c;调试是我们必不可少的技能。在专业…

408数据结构-图的遍历 自学知识点整理

前置知识&#xff1a;图的存储与基本操作 图的遍历是指从图的某一顶点出发&#xff0c;按照某种搜索方法沿着图中的边对图中的所有顶点访问一次&#xff0c;且仅访问一次。因为树是一种特殊的图&#xff0c;所以树的遍历实际上也可以视为一种特殊的图的遍历。图的遍历算法是求解…

利用鱼骨图进行项目问题复盘与改进

一、引言 在项目管理中&#xff0c;问题复盘是一个至关重要的环节。它不仅能帮助我们识别项目执行过程中出现的问题&#xff0c;还能促使我们深入探究问题的根本原因&#xff0c;从而采取有效的改进措施。在这个过程中&#xff0c;鱼骨图作为一种强大的工具&#xff0c;为我们…

MEMS:Lecture 16 Gyros

陀螺仪原理 A classic spinning gyroscope measures the rotation rate by utilizing the conservation of angular momentum. 经典旋转陀螺仪通过利用角动量守恒来测量旋转速率。 Coriolis Effect and Coriolis Force 科里奥利效应是一种出现在旋转参考系中的现象。它描述了…

Internet Download Manager ( 极速下载器 ) 序列号注册码 IDM下载器注册机中文激活破解版

IDM下载器(Internet Download Manager)是一款专业的下载管理软件&#xff0c;它通过多线程技术和智能文件分段技术&#xff0c;有效提升下载速度&#xff0c;并支持断点续传&#xff0c;还具有计划下载功能&#xff0c;用户可以设置特定的下载时间&#xff0c;非常适合需要在特…

代码随想录算法训练营刷题复习1 :动态规划背包问题 01背包+完全背包

动态规划刷题复习 一、01背包 416. 分割等和子集1049. 最后一块石头的重量 II494. 目标和474. 一和零 416. 分割等和子集 class Solution { public:bool canPartition(vector<int>& nums) {int sum0;for(int i0;i<nums.size();i) {sumnums[i];}if(sum%2!0)retu…

IP地址、子网掩码、网段、网关

前面相同就是在同一个网段 如果子网掩码和网络号相与的结果是一样的&#xff0c;那么他们就在同一个子网 IP地址、子网掩码、网络号、主机号、网络地址、主机地址以及ip段/数字-如192.168.0.1/24是什么意思?_掩码248可以用几个ip-CSDN博客

mmsegmentation使用记录

问题1. AssertionError: MMCV2.2.0 is used but incompatible. Please install mmcv>2.0.0rc4. (openmmlab) rootautodl-container-92154ba0e6-51e9a975:~/mmsegmentation# python demo/image_demo.py demo/demo.png configs/pspnet/pspnet_r50-d8_4xb2-40k_cityscapes-512…

谷歌上架,APP被移除了,没封号,换个包名还能重新提审上架?

对于在Google Play上架应用的开发者来说&#xff0c;尤其是那些矩阵式上架马甲包的开发者&#xff0c;可能已经遭遇过无数次应用被暂停或移除的情况了。通常这种情况下&#xff0c;账号也随之会被封&#xff0c;且大多数开发者认为&#xff0c;没有立马收到封号邮件的话&#x…

基于scikit-learn的机器学习分类任务实践——集成学习

一、传统机器学习分类流程与经典思想算法简述 传统机器学习是指&#xff0c;利用线性代数、数理统计与优化算法等数学方式从设计获取的数据集中构建预测学习器&#xff0c;进而对未知数据分类或回归。其主要流程大致可分为七个部分&#xff0c;依次为设计获取数据特征集&#x…

【C++】stack、queue和deque的使用

&#x1f497;个人主页&#x1f497; ⭐个人专栏——C学习⭐ &#x1f4ab;点击关注&#x1f929;一起学习C语言&#x1f4af;&#x1f4ab; 目录 导读 一、stack 1. stack介绍 2. stack使用 二、queue 1. queue介绍 2. queue使用 三、deque 1. deque介绍 2. deque的…

【Pandas驯化-01】一文介绍 Pandas中的Dataframe和Series 区别

【Pandas】驯化-01一文介绍 Pandas中的Dataframe和Series 区别 本次修炼方法请往下查看 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合&#xff0c;智慧小天地&#xff01; &#x1f387; 相关内容文档获取 微信公众…

web前端 Socket:深入探索与实战应用

web前端 Socket&#xff1a;深入探索与实战应用 在Web开发领域&#xff0c;Socket技术以其独特的实时通信能力&#xff0c;为前端开发者提供了全新的交互体验。然而&#xff0c;对于初学者来说&#xff0c;Socket的复杂性和多变的应用场景往往令人感到困惑和挑战。本文将从四个…

用helm安装chart的时候如何使用master的IP

在 Helm chart 中获取 Kubernetes 集群的 master IP 并在安装时将其作为环境变量传递给 Pod 是特定场景下的一个常见需求。要实现这一点&#xff0c;你通常需要两个步骤&#xff1a;首先获取 master 节点的 IP 地址&#xff0c;然后在 Helm chart 的 template 文件中将该 IP 作…

JS常见的运算符有哪些?

在JavaScript中&#xff0c;常见的运算符可以分为以下几类&#xff1a; 算术运算符&#xff1a; &#xff1a;加法-&#xff1a;减法*&#xff1a;乘法/&#xff1a;除法%&#xff1a;取余&#xff08;模运算&#xff09;&#xff1a;递增--&#xff1a;递减**&#xff1a;幂运…

第九届星华杯网络邀请赛

T1喵星人的身高 T2犇犇碑 T3嘤嘤词典 T4三角区间和

简单Mesh多线程合并,使用什么库性能更高

1&#xff09;简单Mesh多线程合并&#xff0c;使用什么库性能更高 2&#xff09;Unity Semaphore.WaitForSignal耗时高 3&#xff09;VS编辑的C#代码注释的中文部分乱码 4&#xff09;变量IntPtr m_cachePtr切换线程后变空 这是第389篇UWA技术知识分享的推送&#xff0c;精选了…

HBase中Master初始化错误~

ERROR&#xff1a;org.apache.hadoop.hbase.PleaseHoldException:Master is initializing 1、停止HBase运行 2、启动zookeeper中的zkCli.sh服务 ./zookeeper/bin/zkCli.sh 3、执行完毕显示以下结果,删除habse文件夹 4、重新启动HBase即可。

python-02

面向对象 Python中把具有相同属性和方法的对象归为一个类。 class ClassName: 语句 class Myclass: # 定义类Myclassdef pp(self): # 定义方法pp()print("这是产品说明书")myclass Myclass() # 实例化类Myclass myclass.pp() # 调用Myclass中的方法pp()打印…