异常的捕获和处理

目录

一、异常

1.异常概述

1.1认识异常

1.2Java异常体系结构

2.Java异常处理机制

2.1异常处理

2.2捕获异常

2.2.1使用try-catch捕获异常

2.2.2使用try-catch-finally处理异常

2.2.3使用多重catch处理异常

2.3抛出异常

2.3.1使用throws声明抛出异常

2.3.2使用throw抛出异常

2.4自定义异常

2.5异常链


一、异常

1.异常概述

1.1认识异常

异常是指程序在运行过程中出现的非正常情况。

public class Main {public static void main(String[] args) {int i=1,j=0,res;System.out.println("begin");res=i/j;//算术运算异常System.out.println("end");}}

一旦程序发生异常将会立即结束,因此“end”没有输出。

1.2Java异常体系结构

异常在Java中被封装成了各种异常类。

程序中常见的异常: 

Exception设计时异常异常层次结构的根类
IOException设计时异常IO异常的根类,属于非运行时异常
FileNotFoundException设计时异常文件操作时,找不到文件
RuntimeException运行时异常运行时异常的根类,RuntimeException及其子类,不要求必须处理
ArithmeticException运行时异常算术运算异常
lllegalArgumentException运行时异常方法接收到非法参数
ArrayIndexOutOfBoundsException运行时异常数组越界访问异常
NullPointerException运行时异常尝试访问null对象的成员时发生的空指针异常
ArrayStoreException运行时异常数据存储异常,写数组操作时,对象或数据类型不兼容
ClassCastException运行时异常类型转换异常
IIIegalThreadStateException运行时异常试图非法改变线程状态,例如试图启动一个已经运行的线程
NumberFormatException运行时异常数据格式异常,试图把一字符串非法转换成数值

2.Java异常处理机制

2.1异常处理

Java中的异常处理机制依靠5个关键字:try、catch、finally、throw、throws。这些关键字提供了两种异常处理方式:

(1)用try、catch、finally来捕获和处理异常

try块中包含可能会抛出异常的代码

catch块中用户捕获和处理指定类型的异常

finally块中的代码无论是否发生异常都会被执行,通常用于释放资源或清理操作

(2)使用throw、throws来抛出异常

throw关键字用于手动抛出异常对象。

throws关键字用于在方法声明中指定可能抛出的异常类型,表示该方法可能会抛出该类型的异常,由调用者来处理。

2.2捕获异常
2.2.1使用try-catch捕获异常
public class Main {public static void main(String[] args) {try {int i=1,j=0,res;System.out.println("begin");res=i/j;System.out.println("end");}catch (Exception e){System.out.println("caught");e.printStackTrace();}System.out.println("over");}}
  • 如果try语句块中的所有语句正常执行完毕,没有发生异常,那么catch语句块中的所有语句将被忽略。
  • 如果try语句块在执行过程中发生异常,并且这个异常与catch语句块中声明的异常类型匹配,那么try语句块中剩下的代码都将被忽略,相应的catch语句块将会被执行。匹配是指catch中所处理的异常类型与try中发生的异常类型完全一致或者是它的父类。
  • 如果try语句块在执行过程中发生异常,而抛出的异常在catch语句块中没有被声明,那么程序立即终止运行,程序被强迫退出。
  • catch语句块中可以加入用戶自定义处理信息,也可以调用异常对象的方法输出异常信息,常用的方法如下:
    void prinStackTrace() :输出异常的堆栈信息。堆栈信息包括程序运行到当前类的执行流程,它将输出从方法调用处到异常抛出处的方法调用的栈序列。
    String getMessage() :返回异常信息描述字符串,该字符串描述了异常产生的原因,是 printStackTrace() 输出信息的一部分。
2.2.2使用try-catch-finally处理异常

无论try块中是否发生异常,finally语句块中的代码总能被执行。

public class Main {public static void main(String[] args) {try {int i=1,j=0,res;System.out.println("begin");res=i/j;System.out.println("end");}catch (ArithmeticException e){System.out.println("caught");e.printStackTrace();}finally {System.out.println("finally");}System.out.println("over");}}
  • 如果try语句块中所有语句正常执行完毕,程序不会进入catch语句块执行,但是finally语句块会被执行。 
  • 如果try语句块在执行过程中发生异常,程序会进入到catch语句块捕获异常, finally语句块也会被执行。
  • try-catch-finally结构中try语句块是必须存在的,catch、finally语句块为可选,但两者至少出现其中之一。

即使在catch语句块中存在return语句,finally语句块中的语句也会执行。发生异常时的执行顺序是,先执行catch语句块中return之前的语句,再执行finally语句块中的语句,最后执行catch语句块中的return语句退出。

finally语句块中语句不执行的唯一情况是在异常处理代码中执行了 System.exit(1) ,退出Java虚拟机。

public class Main {public static void main(String[] args) {try {int i=1,j=0,res;System.out.println("begin");res=i/j;System.out.println("end");}catch (ArithmeticException e){System.out.println("caught");e.printStackTrace();System.exit(1);}finally {System.out.println("finally");}System.out.println("over");}}

public class Main {public static void main(String[] args) {System.out.println(method());}private static int method() {int i=1;try {i++;//2System.out.println("try block,i="+i);//try block,i=2return i;//2}catch (Exception e){i++;System.out.println("catch block,i="+i);}finally {i=10;System.out.println("finally block,i="+i);//finally block,i=10}return i;}
}

 

public class Main {public static void main(String[] args) {System.out.println(method());}private static int method() {int i=1;try {i++;System.out.println("try block,i="+i);//try block,i=2return i;}catch (Exception e){i++;System.out.println("catch block,i="+i);return i;}finally {i=10;System.out.println("finally block,i="+i);//finally block,i=10return i;//10}}
}

2.2.3使用多重catch处理异常

catch语句块的排列顺序必须是从子类到父类,最后一个一般是Exception类。这是因为在异常处理中,catch语句块会按照从上到下的顺序进行匹配,系统会检测每个catch语句块处理的异常类型,并执行第一个与异常类型匹配的catch语句块。如果将父类异常放在前面,子类异常的catch语句块将永远不会被执行,因为父类异常的catch语句块已经处理了异常。

一旦系统执行了与异常类型匹配的catch语句块,并执行其中的一条catch语句后,其后的catch语句块将被忽略,程序将继续执行紧随catch语句块的代码。 

子类异常应该放在前面,父类异常应该放在后面。 

import java.util.InputMismatchException;
import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner input=new Scanner(System.in);try {System.out.println("计算开始:");int i,j,res;System.out.println("请输入被除数:");i=input.nextInt();System.out.println("请输入除数:");j=input.nextInt();res=i/j;System.out.println(i+"/"+j+"="+res);System.out.println("计算结束");}catch (InputMismatchException e){System.out.println("除数和被除数都必须是整数!");}catch (ArithmeticException e){System.out.println("除数不能为0!");}catch (Exception e){System.out.println("其他异常"+e.getMessage());}finally {System.out.println("感谢使用本程序!");}System.out.println("程序结束!");}}

第一种:被除数发生异常

 

 第二种:除数发生异常

第三种:除数为0

2.3抛出异常
2.3.1使用throws声明抛出异常

如果在一个方法体内抛出了异常,并希望调用者能够及时地捕获异常,Java语言中通过关键字throws声明某个方法可能抛出的各种异常,以通知调用者。throws可以同时声明多个异常,之间用逗号隔开。

import java.util.InputMismatchException;
import java.util.Scanner;public class Main {public static void main(String[] args) {try {divide();}catch (InputMismatchException e){System.out.println("除数和被除数都必须是整数!");}catch (ArithmeticException e){System.out.println("除数不能为0!");}catch (Exception e){System.out.println("其他异常"+e.getMessage());}finally {System.out.println("感谢使用本程序!");}System.out.println("程序结束!");}private static void divide() throws Exception{Scanner input=new Scanner(System.in);System.out.println("计算开始:");int i,j,res;System.out.println("请输入被除数:");i=input.nextInt();System.out.println("请输入除数:");j=input.nextInt();res=i/j;System.out.println(i+"/"+j+"="+res);System.out.println("计算结束");}}
2.3.2使用throw抛出异常

在Java语言中,可以使用throw关键字来自行抛出异常。

package structure;public class Main {public static void main(String[] args) {Person1 person=new Person1();try {person.setName("扈三娘");person.setAge(18);person.setGender("男女");person.print();}catch (Exception e){e.printStackTrace();}}
}
class Person1{private String name="";private int age=0;private String gender="男";public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getGender() {return gender;}public void setGender(String gender) throws Exception{if ("男".equals(gender)||"女".equals(gender)){this.gender = gender;}else {throw new Exception("性别必须是男或女!");}}public void print(){System.out.println("姓名:"+this.name+"性别:"+this.gender+"年龄:"+this.age);}
}

  • 如果 throw 语句抛出的异常是 Checked 异常,则该 throw 语句要么处于 try 块里,显式捕获该异常,要么放在一个带 throws 声明抛出的方法中,即把该异常交给该方法的调用者处理; 
  • 如果 throw 语句抛出的异常是 Runtime 异常,则该语句无须放在 try 块里,也无须放在带 throws 声明抛出的方法中;程序既可以显式使用 try...catch来捕获并处理该异常,也可以完全不理会该异常,把该异常交给该方法调用者处理。
  • 自行抛出Runtime 异常比自行抛出Checked 异常的灵活性更好。同样,抛出 Checked 异常则可以让编译器提醒程序员必须处理该异常。

 throw和throws的区别:

1.作用不同:throw用于程序员自行产生并抛出异常,throws用于声明该方法内抛出了异常。
2.使用位置不同:throw位于方法体内部,可以作为单独的语句使用;throws必须跟在方法参数列表的后面,不能单独使用。
3.内容不同:throw抛出一个异常对象,只能是一个;throws后面跟异常类,可以跟多个。

2.4自定义异常

当JDK中的异常类型不能满足程序的需要时,可以自定义异常类。步骤:

①定义异常类,并继承Exception或者RuntimeException。

②编写异常类的构造方法,向父类构造方法传入异常描述信息,并继承父类的其他实现方法。

③实例化自定义异常对象,并在程序中使用throw抛出。

package structure;public class Main {public static void main(String[] args) {Person1 person=new Person1();try {person.setName("扈三娘");person.setAge(18);person.setGender("男女");person.print();}catch (GenderException e){e.printStackTrace();}}
}
//自定义异常类
class GenderException extends Exception{public GenderException(String message){super(message);}
}
class Person1{private String name="";private int age=0;private String gender="男";public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getGender() {return gender;}public void setGender(String gender) throws GenderException{if ("男".equals(gender)||"女".equals(gender)){this.gender = gender;}else {throw new GenderException("性别必须是男或女!");}}public void print(){System.out.println("姓名:"+this.name+"性别:"+this.gender+"年龄:"+this.age);}
}

自定义异常可能是编译时异常,也可能是运行时异常 。

1.如果自定义异常类继承Excpetion,则是编译时异常。
特点:方法中抛出的是编译时异常,必须在方法上使用throws声明,强制调用者处理。
2.如果自定义异常类继承RuntimeException,则运行时异常。
特点:方法中抛出的是运行时异常,不需要在方法上用throws声明。

2.5异常链

有时候我们会捕获一个异常后再抛出另一个异常。

顾名思义就是将异常发生的原因一个传一个串起来,即把底层的异常信息传给上层,这样逐层抛出。

在要抛出的对象中使用 initCause() 方法,添加上一个产生异常的信息; getCause() 可以获取当前异常对象的上一个异常对象。

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

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

相关文章

etcd读写请求的执行过程

etcd读请求如何执行 首先,etcdctl 会对命令中的参数进行解析。在解析完请求中的参数后,etcdctl 会创建一个 clientv3 库对象通过gRPC API来访问 etcd server。对应流程一。 然后通过负载均衡算法选择一个etcd server节点,然后调用 etcd ser…

【计算机组成 课程笔记】2.1 设计自己的计算机

课程链接: 计算机组成_北京大学_中国大学MOOC(慕课) 2 - 1 - 201-设计自己的计算机(14‘24’‘)_哔哩哔哩_bilibili 什么是指令系统体系结构?这个问题其实非常简单,但要想解释清楚也没有那么容易。我们还是从一个小故事…

机器学习技术(六)——有监督学习算法之线性回归算法实操

机器学习技术(五)——有监督学习之线性回归算法实操 引言: 机器学习监督算法是一种基于已有标记数据的学习方法,通过对已知输入和输出数据的学习,建立一个模型来预测新的输入数据的输出。这种算法模仿人类的学习过程&a…

Pycharm保存自定义布局

1.启用特定窗口 在View->Tool Windows下可以启用特定窗口,窗口标签会出现在左边(图中红框处),下边或右边,可以拖动摆放位置 2.保存 在windows->layout下可以选择保存布局 1.图中第一个选项:选择或…

【Kafka】Kafka Stream简单使用

一、实时流式计算 1. 概念 一般流式计算会与批量计算相比较。在流式计算模型中,输入是持续的,可以认为在时间上是无界的,也就意味着,永远拿不到全量数据去做计算。同时,计算结果是持续输出的,也即计算结果…

计算机网络(速率、宽带、吞吐量、时延、发送时延)

速率: 最重要的一个性能指标。 指的是数据的传送速率,也称为数据率 (data rate) 或比特率 (bit rate)。 单位:bit/s,或 kbit/s、Mbit/s、 Gbit/s 等。 例如 4 1010 bit/s 的数据率就记为 40 Gbit/s。 速率往往是指额定速率或…

设计模式--代理模式(Proxy Pattern)

一、什么是代理模式(Proxy Pattern) 代理模式(Proxy Pattern)是一种结构型设计模式,它允许一个对象(代理)充当另一个对象(真实对象)的接口,以控制对该对象的…

video标签在安卓手机内置浏览器上的播放问题

道阻且长,行而不辍,未来可期 问题: 在手机内置浏览上,虽然没有给video标签设置controls,但在内置浏览器上,就是会显示。 而且,video一旦自动播放,video的层级就会提升到最前,想设置一个盒子覆盖…

lambda 表达式

C自学精简实践教程 目录(必读) 什么是lambda表达式? lambda表达式实际上就是一个类似函数的可以被调用的对象。 和函数一样可以使用圆括号调用。 只不过,这个函数可以定义在代码的任意位置。非常的灵活,自由。而函数不能定义在其他函数的…

【数据结构】多叉树转换为二叉树-c++代码实现-POJ 3437 Tree Grafting

文章目录 写这个题目的原因寻找提交网址题目解决思路AC代码成功AC 写这个题目的原因 1、今天在看王道考研数据结构的课(虽然我要保研,但是因为这些看保研面试的时候会问,所以看一下嘞orz),看到了这个多叉树转换为二叉…

【YOLOV5】YOLOV5添加SPPCSPC

当前YOLOV5版本为7.0 第一步 在models/common.py添加SPPCSPC class SPPCSPC(nn.Module):# CSP https://github.com/WongKinYiu/CrossStagePartialNetworksdef __init__(self, c1, c2, n1, shortcutFalse, g1, e0.5, k(5, 9, 13)):super(SPPCSPC, self).__init__()c_ int(2 *…

CS144(2023 Spring)Lab 0:networking warmup(环境搭建 webget bytestream)

文章目录 前言其他笔记相关链接 1. Set up GNU/Linux on your computer2. Networking by hand3. Writing a network program using an OS stream socket3.1 Linux配置3.2 C规范3.3 Writing webget3.3.1 实现3.3.2 测试 4. An in-memory reliable byte stream4.1 思路分析4.2 代…