异常是指程序的运行过程中所发生的不正常事件,如所需文件找不到,网络连接不通或连接中断、算术运算出错(如被零整除)、数组下标越界、装载一个不存在的类、对null对象操作、类型转换异常。异常会中断正在运行的程序。
所有异常类型都是Throwable类的子类,它派生了两个子类:Error类和Exception类。
(1).Error类:表示仅靠程序无法恢复的严重错误,如内存溢出、动态链接失败、虚拟机错误,应用程序不应该抛出这种类型的错误(一般由虚拟机抛出)。假如出现这种错误,应尽力使程序安全退出。
(2)Exception类:由Java应用程序抛出和处理的非严重错误,如所需文件找不到,网络连接不同通或连接中断,算术运算出错(如被零除)、数组下标越界,装载一个不存在的类,对null对象操作,类型转换异常等。它的各种不同的子类分别对应不同类型的异常,Exception又可分为两大类异常。
a.运行异常:包括RuntimeException及其所有子类。不要求程序对他们进行处理,如算术异常ArithmeticException
b.Checked异常(非运行时异常):除了运行时异常外的其他从Exception类继承来的的异常
下表列出常见的异常:
异常 | 说明 |
---|---|
Exception | 异常层次结构的根类 |
ArithmeticException | 算术错误异常,如以零作为除数 |
ArrayIndexOutOfBoundsException | 数组下标越界异常 |
NullPointerException | 尝试访问null对象成员 |
ClassNotFoundException | 不能加载所需要的类 |
InputMismatchException | 欲得到的数据类型与实际输入的类型不匹配 |
IllegalArgumentException | 方法接收到非法参数 |
ClassCastException | 对象强制类型转换出错 |
NumberFormatException | 数字格式转换异常,如把“abc”转换成数字 |
异常处理机制就像人们对平时可能遇到的意外情况,预先想好了一些处理的办法。在程序执行代码时,若发生了异常,程序会按照预定的处理办法对异常进行处理,异常处理完毕后,程序继续运行(不加异常处理,程序不会继续运行下面的代码)。
Java的异常处理是通过5个关键字来实现的,即try、catch、finally、throw和throws。
Java中提供了try-catch结构进行异常捕获处理,把可能出现异常的代码放入try语句块中,并使用catch语句捕获异常。
快捷键:选中代码,同时按下Ctrl+Alt+t
就可以捕获异常。
使用try-catch捕获并处理示例1中的异常
public static void main(String[] args) {
try {
Scanner scanner =new Scanner(System.in);
System.out.println("请输入被除数");
int num1 =scanner.nextInt();
System.out.println("请输入除数:");
int num2=scanner.nextInt();
System.out.println(String.format("%d/%d=%d",num1,num2,num1/num2));
System.out.println("感谢使用本程序");
} catch (Exception e) {
System.err.println("出现错误:被除数和除数必须是整数,"+"除数不能为零");
e.printStackTrace();
}
}
分析:
try-catch语句块的执行流程比较简单,首先执行的是try语句块中的语句,这时可能会出现以下3种情况。
(1)如果try语句块中所有语句正常执行完毕,没有发生异常,那么catch语句块中的所有语句都将会被忽略。当在控制台输入两个整数时,示例3中的try语句块中的代码将正常执行,不会执行catch语句块中的代码。输出结果
请输入被除数
200
请输入除数:
4
200/4=50
感谢使用本程序
(2)如果try语句块在执行过程中发生异常,并且这个异常与catch语句块中声明所示。的异常类型匹配,那么try语句块中剩下的代码都将被忽略,而相应的catch语句块将会被执行。匹配是指catch所处理的异常类型与所生成的异常类型完全一致或是它的父类。当在控制台提示输出被除数时,输入了"B",示例3中try语句块中的代码:
"int num1 =in.nextInt();"将抛出InputMismatchException异常。由于InputMismathException是Exception的子类,程序将忽略try语句中剩下的代码而去执行catch语句块。输出结果如下
请输入被除数
200
请输入除数:
B
出现错误:被除数和除数必须是整数,除数不能为零
java.util.InputMismatchException
如果输入的除数为0,输出的结果如下
请输入被除数
200
请输入除数:
0
出现错误:被除数和除数必须是整数,除数不能为零
java.lang.ArithmeticException: / by zero
(3)如果try语句块在执行过程中发生异常,而抛出的异常在catch语句中没又被声明,那么方法立刻退出
如示例3所示,在catch语句块中可以加入用户自定义处理信息,也可以调用异常对象的方法输出异常信息,常用方法如下:
a.void printStackTrace():堆栈信息包括程序运行到当前类的执行流程,它将输出从方法调用处到异常抛出处的方法调用实例。
b.String getMessage():返回异常信息描述的字符串,该字符串描述了异常产生的原因,是printStackTrace()输出的信息的一部分。
注意:
如果try语句块在执行过程中发生异常,try语句块中剩下的代码都将被忽略,系统会自动生成相应的异常对象,包括异常的类型、异常出现时程序的运行状态及对该异常的详细描述。如果这个异常对象与catch语句块中声明的异常类型匹配,会把该异常对象赋给catch后面的异常参数,相应的catch语句块将会被执行。
如果希望示例3中不管是否发生异常,都执行输出”感谢使用本程序!“语句,就需要在try-catch语句块后加入finally语句块,把要执行输出的语句放入finally语句块中,无论是否发生异常,finally语句块中的代码总能被执行。
public static void main(String[] args) {
try {
Scanner scanner =new Scanner(System.in);
System.out.println("请输入被除数");
int num1 =scanner.nextInt();
System.out.println("请输入除数:");
int num2=scanner.nextInt();
System.out.println(String.format("%d/%d=%d",num1,num2,num1/num2));
} catch (Exception e) {
System.err.println("出现错误:被除数和除数必须是整数,"+"除数不能为零");
e.printStackTrace();
}finally {
System.out.println("/by zero");
System.out.println("感谢使用本程序");
}
}
分析:
try-catch-finally语句块的执行流程大致分为如下两种情况。
(1)如果所语正常执行完毕,finally语句块也会被执行,例如,当在控制台输入两个数字时,示例4中的try语句块中的代码将正常执行,不会执行 catch-fnally代将被执行输出结果如下所示。
请输入被除数
200
请输入除数:
0
/by zero
感谢使用本程序
出现错误:被除数和除数必须是整数,除数不能为零
(2)如果异常,无这种异常能否被catch语句块捕获到,将行finally语句中的代码。例,当在控制台输入的除数为0时,示例4中的try语句块中将抛出异常,进入catch句块finally语句块中的代码也将被执行输出结果如图97所示。
try-catch-finally结构中try语句块是必须存在的,catch、finally语句块为可选,但两者至少出现其中之一。
需要特别注意的是,即使在catch语句块中存在retun语句,finally语句块中的语句也会执行。发生异常时的执行顺序是,先执行catch块中retun之前的语句,再执行finally语句块中的语句,最后执行catch语句块中的return语句退出。
finally语句块中语句不执行的唯一情况是在异常处理代码中执行System.exit(1)退出Java虚拟机。如下示例5
示例
在try-catch-finally结构的catch语句块中执行System.exit(1)退出Java虚拟机
public static void main(String[] args) {
try {
Scanner scanner =new Scanner(System.in);
System.out.println("请输入被除数:");
int num1 =scanner.nextInt();
System.out.println("请输入除数");
int num2=scanner.nextInt();
System.out.println(String.format("%d/%d=%d",num1,num2,num1/num2));
} catch (Exception e) {
System.err.println("出现错误:被除数和除数必须是整数,"+"除数不能为零");
System.exit(1); //finally 语句块不执行的唯一情况
//return;如果用return,finally代码块依旧执行
} finally {
System.out.println("感谢使用本程序");
}
}
在计算并,输出商的示例中,至少存在两种异常情况,输入非整数内容和除数为0,在示例4中,统一按照Exception类型捕获,其实可以使用多重catch语句块分别捕获并处理对应异常。
一段代码可能会引发多种类型的异常,这时,可以在一个try语句块后面跟多个catch语句块分别处理不同的异常。但排列顺序必须是从子类到父类,最后一个一般都是Exception类。因为按照匹配原则,如果父类异常放到前面,后面的catch语句块将不会有被执行机会。
运行时,系统从上到下分别对每个catch语句块处理的异常类型进行检测,并执行第一个与异常类型匹配的catch语句。执行其中的一条catch语句后,其后的catch语句将被忽略。
示例
对示例4进行修改
public static void main(String[] args) {
try {
Scanner scanner =new Scanner(System.in);
System.out.println("请输入被除数");
int num1 =scanner.nextInt();
System.out.println("请输入除数");
int num2 =scanner.nextInt();
System.out.println(String.format("%d/%d=%d",num1,num2,num1/num2));
} catch (InputMismatchException e) {
System.err.println("被除数和除数必须是整数。");
} catch (ArithmeticException e){
System.err.println("除数不能为0");
}catch (Exception e){
System.err.println("其他未知的异常");
}finally {
System.out.println("感谢使用本程序");
}
}
程序运行后,如果输入的不是整数,系统会抛出InputMismatchException异常对象,因此进入第一个catch语句块,并执行其中的代码,而其后的catch语句块将被忽略。输出结果如下:
请输入被除数
0.2
感谢使用本程序
被除数和除数必须是整数。
如果系统提示输入被除数时输入“200”,系统会接着提示输入除数,当输入“0”时,系统会抛出ArithmeticException异常对象,因此进入第二个catch语句块并执行其中的代码块,其他的catch语句块将被忽略,如下:
请输入被除数
200
请输入除数
0
感谢使用本程序
除数不能为0
提示:
在使用多重catch语句块时,catch语句块的排列顺序必须是从子类到父类,最后一个一般都是Exception类。下面代码片断是错误的。
提示爆红:Exception ‘java.lang.ArithmeticException’ has already been caught
已捕获异常“java.lang.ArithmeticException”
原因:我们父类异常放在子类的异常前面,然而父类的异常涵盖了子类的异常
示例:
catch (Exception e){
System.err.println("其他未知的异常");
} catch (ArithmeticException e){ //提示爆红
System.err.println("除数不能为0");
}finally {
System.out.println("感谢使用本程序");
}
如果一个方法体中抛出了异常,并希望调用者能够及时的捕获异常,Java语言中通过关键字throws声明某个方法可能抛出的方法中异常以通知调用者。throws可以同时声明多个异常,之间用,号隔开
下面的示例,把计算输出商的任务封装在了divide()方法中,并在方法的参数列表后通过throws声明抛了异常,然后在main()方法就知道divide()方法中抛出了异常,可以采用如下两种方法进行处理
1).通过try-catch捕获并处理·异常
2)通过throws继续声明异常,如果调用者不知道如何处理该异常,可以继续通过throws声明异常,让上一级调用者处理异常。main()方法的异常将由Java虚拟机处理。
示例:
在Java程序中使用throws声明抛出异常
public static void main(String[] args) {
try {
divide();
} catch (InputMismatchException e) {
System.err.println("被除数和除数必须是整数");
} catch (ArithmeticException e) {
System.err.println("除数不能为0");
} catch (Exception e) {
e.printStackTrace();
}finally {
System.out.println("感谢使用本程序!");
}
}
//通过throws声明抛出异常
public static void divide() throws Exception{
Scanner scanner =new Scanner(System.in);
System.out.println("请输入被除数");
int num1 =scanner.nextInt();
System.out.println("请输入除数");
int num2 =scanner.nextInt();
System.out.println(String.format("%d/%d=%d",num1,num2,num1/num2));
}
除了系统自动抛出异常外,在编程过程中,有些问题是系统无法自动发现解决的,如果年龄不在正常范围内,性别输入不是“男”或“女”等,此时需要程序而不是系统来自行抛出异常,把问题交给调用者去解决。
在Java语言中,可以使用throw关键字来自行抛出异常。在下面示例9的带码中抛出了异常,抛出异常的原因在于当前环境无法解决参数问题,因此在方法内部通过throw抛出异常,把问题交给调用者解决。
示例:
在Java程序中使用throw抛出异常。
1).先创建一Person类
public class Person {
private String name=""; //姓名
private int age =0; //年龄
private String sex="男"; //性别
//设置性别
public void setSex(String sex)throws Exception{
if ("男".equals(sex)||"女".equals(sex)) {
this.sex=sex;
}else {
throw new Exception("性别必须是\"男\"或者\"女\"!");
}
}
//输出基本信息
public void print(){
System.out.println(this.name+"("+this.sex+","+this.age+"岁)");
}
}
2).测试
public static void main(String[] args) {
Person person = new Person();
try {
person.setSex("man");
person.print();
} catch (Exception e) {
e.printStackTrace();
}
}
3)运行结果:
java.lang.Exception: 性别必须是"男"或者"女"!
at com.shujia.Person.setSex(Person.java:23)
at com.shujia.Test8.main(Test8.java:17)
Process finished with exit code 0
注意:
throw和throws的区别如下:
1).作用不同:throw用于程序员自行产生并抛出异常,throws用于声明该方法内抛出了异常。
2).使用的位置不同:throw位于方法体内部,可以作为单独语句使用;throws必须跟在方法参数列表的后面,不能单独使用。
3)内容不同:throw抛出一个异常对象,只能是一个;throws后面跟异常类,可以跟多个。
当JDK中的异常类型不满足我门需求,我门就可以自定义异常。
自定义异常:
1.定义异常类,继承Exception或者RuntimeException
2.编写一个异常类并编写一个构造方法,并继承父类的实现。
public Exception() {
super();//调用了父类的无参构造方法
}
public Exception(String message) {
super(message);//调用了父类里面带String的参数的构造方法
}
//现在所有的Throwable的子类构造器中都可以接收一个cause对象作为参数,这这参数就是异常的原由,代表的原始异常,即使在当前位置创建并抛出行的异常,也可以通过这个cause追踪到异常最初发生的位置。
public Exception(String message, Throwable cause) {
super(message, cause);//调用了父类含有cause参数的构造函数
}
public Exception(Throwable cause) {
super(cause);
}
背景: 在异常处理时:A方法调用了B方法,B方法抛出了异常,那么A方法是继续抛出原有的异常还是抛出个新异常
如果抛出原有的异常将是很糟糕的设计方法。因为A方法与B方法进行了关联,不便于代码的修改和扩展,若抛出新的异常,虽然解决了A方法和B方法的关联问题,但是原有的异常信息却会丢失。JDK1.4推出了异常链,解决了这个问题,所有的Throwable的子类在构造器中都可以接收一个cause对象作为参数。这个cause就用来表示原始异常,这样可以把原始异常传递给新的异常,使得即使在当前位置创建并抛出新的异常,你也能通过这个异常链跟踪到异常最初发生的位置。
通俗的来讲:把捕获的异常包装成一个新的异常,在新的异常中添加对新的异常的引用,再把新异常抛出,就像是链式反应一样,这种就叫异常链。
1.异常就是在程序的运行过程中所发生的异常事件
2.Java处理异常通过5个关键字来实现,,try、catch、finally、throw、throws
3.即使在try语句块,catch语句中存在return语句,finally语句块也会去执行,finally语句块中不执行的原因,唯一原因,在异常处理代码中执行了System.exit(1).跳出了Java虚拟机
4.可以在try语句块后面跟多个catch语句块,分别处理不同的异常,但是排序必须是从·特殊异常到一般异常,最后一个一般是Exception类
5.Java语言通过关键字throws声明某个方法可能抛出的各种异常以通知调用者
6.在Java语言中,通过throw关键字来自行抛出异常
7.自定义异常一般需要继承Execption或者RuntimeException
文章浏览阅读3w次,点赞65次,收藏374次。内容目录(原文见公众号python宝或www.xmmup.com)一、打断点二、代码调试三、界面小图标介绍四、控制台介绍# 数字转换为大写人民币import sysimport io..._pycharm debug
文章浏览阅读4.7k次。1、配置layout<?xml version="1.0" encoding="utf-8"?><LinearLayout ="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" >_mediaplayer glsurfaceview
文章浏览阅读5.2k次,点赞76次,收藏106次。本文从战略(宏观)和战术(微观)两个层次讲解提示词技巧。希望大家能够掌握常见的提示词技巧,能够在 AI 早期积极主动学习,占领先机。_大模型提示词
文章浏览阅读2.4k次,点赞3次,收藏3次。建了一个简单web项目,但是项目出了一个Description Resource Path Location TypeDescription Resource Path Location TypeThe superclass “javax.servlet.http.HttpServlet” was not found on the Java Build Path index.jsp /s..._"descriptionresourcepathlocationtype the superclass \"javax.servlet.http.h"
文章浏览阅读1.8k次。1. Download Sun Java JDK or JRE Download Sun Java JDK or JRE from here (current version is JDK 6 Update 20)http://java.sun.com/javase/downloads/index.jsp.Note: you can Skip login step.Download rpm.bin package (example jdk-6u20-linux-i586-rpm.bin).2. Change_fedora install jdk
文章浏览阅读108次。_andori拍照返回app 崩溃
文章浏览阅读7w次,点赞271次,收藏1.1k次。最近在微信公众号里看到多篇讲解yolov5在openvino部署做目标检测文章,但是没看到过用opencv的dnn模块做yolov5目标检测的。于是,我就想着编写一套用opencv的dnn模块做yolov5目标检测的程序。在编写这套程序时,遇到的bug和解决办法,在这篇文章里讲述一下。在yolov5之前的yolov3和yolov4的官方代码都是基于darknet框架的实现的,因此opencv的dnn模块做目标检测时,读取的是.cfg和.weight文件,那时候编写程序很顺畅,没有遇到bug。但是yolo_opencv yolov5
文章浏览阅读168次。牛客小白月赛20D 3的倍数题目链接算法分析n最大为15,范围比较小,所以直接来采用爆搜就行算法实现#include<iostream>#include<cstdio>#include<string>#include<cstring>#include<math.h>using namespace std;int ch[20][30];//ch[i][j]记录第i个字符串中j的个数,j为字符转换后的数字int dp[30];/_3的倍数csdn
文章浏览阅读71次。本文来自于腾讯优测公众号(wxutest),未经作者同意,请勿转载,原文地址:https://mp.weixin.qq.com/s/806TiugiSJvFI7fH6eVA5w作者:腾讯TMQ专项测试团队导语最近小优听说,隔壁的腾讯TMQ团队出了一本新书——《移动App性能评测与优化》,便借阅了一本,读完感觉写得确实很赞。这本书体系化地介绍了移动应用性能评测与优化的方方面面,如内存,电量..._如何降低app的待机内存
文章浏览阅读1.6k次,点赞21次,收藏6次。Texlive2020+Texstudio2.12.22资源,附安装教程和刘海洋latex入门使用说明书百度云地址文件截图![\[\]](https://img-blog.csdnimg.cn/20201031105628261.png#pic_center)总结百度云地址链接:https://pan.baidu.com/s/1w4ZdEHvgMBF2uURQmnAxXw提取码:6jga复制这段内容后打开百度网盘手机App,操作更方便哦–来自百度网盘超级会员V1的分享文件截图总结如果链接..
文章浏览阅读5.2k次。题目大意:有一种汉堡,用B、S、C三种原料做成,现在告诉你当前有的B、S、C的个数,到商店买的B、S、C的单价(商店无限供应这三种原料),还有你拥有的钱。问最多能做多少个汉堡。刚开始我还以为是模拟,先把能用的用完,再去买。但是写了半天写不下去了,找了一下题解才发现是二分答案板子题。发现自己对二分还是不是很敏感。AC代码://https://blog.csdn.net/hesorche..._hamburger题解
文章浏览阅读1.9k次。提示:安装uhd+gnuradio实际上并不难,只是实际安装的时候,作为新手经常会因为缺乏相关知识而踩不少坑,以下是我踩坑安装的一些记录。gnuradio+uhd安装过程ubuntu下安装uhd+gnuradioExample: For UHD 3.9.5:Example: For UHD 3.14.0.0win10下安装ubuntu双系统使用usrpb210ubuntu18.04安装方法有两种,一种是使用已经编译好的二进制码,缺点是版本通常比较旧,但学习usrp也不需要太新的版本,另外,这种_无法定位软件包 libuhd003