Java异常处理(详解)

news2024/9/21 4:20:29

Java异常处理

  • 前言
  • 一、异常与异常类
    • 1.异常的概念
    • 2.异常类
      • Error类
      • Exception类
        • (1)非检查异常
        • (2)检查异常
  • 二、异常处理
    • 1.异常的抛出与捕获
    • 2.try-catch-finally语句
    • 3.声明方法抛出异常
    • 3.用throw 语句抛出异常
  • 三、自定义异常类


前言

如同大多数现在现代编程一样,Java语言有着健壮的异常处理机制,将控制权从出错点转移给强壮的错误处理器,这篇文章为大家主要讲解Java的异常处理机制。


一、异常与异常类

1.异常的概念

所谓异常是在程序运行过程中产生的使程序终止正常运行的错误对象,如数组下标越界,整数除法中零作除数,文件等找不到等都可能使程序终止运行。

我们看下面的一段程序

package com.demo
public class InputChar{
	public static void main(String[] args){
		System.out.print("请输入一个字符:");
		char c= (char) =System.in.read(); 		//改行发生编译错误
		System,out.println("c= "+c);
	}
}

当编译该程序时会出现下列编译错误:

Unhandled exception type IOException

错误原因是程序没有处理IOException异常,该异常必须捕获或声明抛出。出现编译错误的原因是,read()方法在定义的时候声明抛出了IOException异常,因此程序中调用该方法必须对该类作异常处理



2.异常类

java语言的异常处理定义了多种类,其中所有异常类都是Throwable的子类,是Object的直接子类,Throwable有两个子类,一个是Error类,另一个是Exception类,这两个子类又分为若干个子类

下图展示了Throwable类及其常见子类的层次结构

在这里插入图片描述



Error类

Error类描述的是系统内部错误,这样的错误很少出现,如果发生了这类错误,则除了通知用户及终止程序外,几乎什么也不能做,程序中一般不对这类错误处理



Exception类

(1)非检查异常

非检查异常是RuntimeException类及其子类异常,也称为运行时异常。

常见的非检查异常如下图所示:

在这里插入图片描述

非检查异常是在程序运行时检测到的,可能发生在程序的任何地方且数量较大,因此编译器不对非检查异常(包括Error类的子类)处理,这种异常又称为免检异常


程序运行时发生非检查异常时运行时系统会把异常对象交给默认的异常处理程序,在控制台显示异常的内容及其发生异常的位置:

下面介绍几种常见的非检查异常:

  1. NullPointerException:空指针异常,即某个对象为null时调用该对象的方法或使用对象就会产生该异常
  2. ArithmeticException:算术异常,在做整数的除法或者整数的求余运算时可能产生的异常,它是在除数为0时产生的异常
  3. ClassCastException:对象转换异常,Java支持对象类型转换,若不符合转换的规定,则产生类转换异常
  4. ArrayIndexOutOfBoundsException:数组下标越界异常,当引用数组元素的下标超出范围时产生的异常。
  5. NumberFormatException:数字格式错误异常,在将字符串转换为数值时,如果字符串不能正确转换成数值则产生该异常

注意:尽管编译器不对非检查异常处理,但程序运行时产生这类异常,程序也不能正常结束,为了保证程序正常运行,要么避免产生非检查异常,要么对非异常检查进行处理



(2)检查异常

检查异常是除RuntimeException类及其子类以外的异常类,有时候也成为必检异常,对这类异常,程序必须捕获或者声明抛出,否则编译器不会通过。上图中的read()方法声明抛出的IOException异常就是必检异常。例如,若试图使用Java命令运行一个不存在的类,则会产生ClassNotFoundException异常,若调用了一个不存在的方法,则会产生NoSuchMethodException
异常



二、异常处理

1.异常的抛出与捕获

异常是在方法中产生的,方法中如果在运行过程中产生了异常,在这个方法中就产生一个代表该异常类的对象,并把它交付给系统,运行时系统寻找相应的代码来处理该异常,这个过程称为抛出异常

关于main()方法中调用情况如下图所示:

在这里插入图片描述

main()方法调用methodA()方法,methodA()调用methodB()方法,methodB()调用methodC()方法。
假如在methodC()方法中发生了异常,运行时首先在该方法中寻找处理异常的代码,如果找不到,运行时系统将在方法调用栈中回溯,把异常对象交给methodB()方法,如果methodB()方法也没有异常处理的代码,将继续回溯,直到找到处理异常的代码,最后,如果main()方法中也没有处理异常的代码,运行时系统将异常交给JVM
,JVM将在控制台显示异常信息



2.try-catch-finally语句

捕获并处理异常最常用的方法就是用try-catch-finally语句,一般格式为:

try{
	//需要处理的代码或者是可能会出现异常的代码
}catch(ExceptionType1 exceptionObject){
	//异常处理的代码
}[catch(ExceptionType1 exceptionObject)]{
	//异常处理的代码
}
finally{
	//最后处理的代码
}]

说明:
(1). catch块用来捕获异常,括号中指明捕获的异常类型及其异常引用名,类似于方法的参数,指明catch语句所处理的异常
注意:若有多个catch块,异常类型的排列顺序必须按照从特殊到一般的顺序,即子类异常放前面,父类异常放在后面,否则会产生编译错误


(2).finally块是可选项,异常的产生往往会中断应用程序的执行,而在异常产生前,可能有些资源没被释放。有时无论程序是否发生异常,都要执行一段代码,这是就可以用finally块来实现,即使是使用了return语句,finally块都会被执行,除非catch块中调用了System.exit()方法终止了程序的运行

(3).一个块中必须要有一个catch块或者finally块,即都不能单独使用


(4).catch块中可以捕获多个异常,例如:
catch(ExceptionType1 exceptionObject| Exception Type2 exception){ …}


下图展示用一个try-catch结构捕获并且处理一个ArithmeticException异常

在这里插入图片描述

注意在异常类的根类定义了其他方法:如下所示

public void printStackTrace():在标准错误的输出流上输出异常调用栈的轨迹

public String getMessage():返回异常对象的细节描述

public String toString():返回对象的简短描述,是Object类中同名方法的覆盖


3.声明方法抛出异常

有时候方法产生的异常不需要再该方法中处理,可能需要由该方法的调用方法处理,这是可以在声明方法时用throw子句声明抛出异常,将该异常传递给调用该方法的方法处理
按上述的方式声明的方法,就可对方法中产生的异常不作处理,若方法内抛出了异常,则调用该方法的方法必须捕获这些异常或再声明抛出

下图为例:

在这里插入图片描述


注意:前面讲到子类可以覆盖父类的方法,但若父类的方法使用throws声明抛出了异常,子类方法也可以使用throws方法声明异常。但是要注意,子类方法抛出的异常必须是父类方法抛出的异常或子异常

下面为例:

class AA{
	public void test() throws IOException{
		System.out.println("In AA's test()")
	}
}

class BB extends AA{
	public void test() throws FileNotFounfException{		//允许,FileNotFounfException是IOException的子类
		System.out.println("In AA's test()")
	}
}

class CC extends AA{
	public void test() throws Exception{		//错误,Exception是IOException的父类
		System.out.println("In AA's test()")
	}
}


3.用throw 语句抛出异常

到目前为止,处理的异常都是由程序产生的,并由程序自动抛出,然而也可以创建一个异常对象,然后用throw语句抛出,或将捕获到的异常对象由throw语句再次抛出,throw语句的格式如下

throw throwableInstance

throwableInstance可以是用户创建的异常对象,也可以是程序捕获到的异常对象,该实例必须是Throwable类或者其子类的实例

下图为例:

在这里插入图片描述

注意看图中的序号1,若去掉throw e 这个语句,那么main()主函数中将接受不到方法抛出的异常,因为该方法已经处理了这个异常,大家可以对比这两种图的结果,下图为去掉序号1语句后的结果


在这里插入图片描述



三、自定义异常类

尽管Java已经预定义了许多异常类,但有时还需要定义自己的异常。编写自定义异常类实际上是一个继承API标准异常类,用新定义的异常类处理信息覆盖原有信息的过程。

常用的编写自定义异常类的模式如下:

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

下面讨论一个例子。假设程序中需要验证用户输入的数据值是否必须是正值,可以按照以上模式编写自定义异常类如下:

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

下图为例:

在这里插入图片描述



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

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

相关文章

Springboot微服务项目整合skywalking链路追踪框架

skywalking官网网址:Apache SkyWalking 目录 1、安装skywalking 2、微服务接入skywalking 3、skywalking数据持久化 1、安装skywalking 下载skywalking,本篇文章使用的skywalking版本是8.5.0 Index of /dist/skywalkinghttps://archive.apache.org/…

JL653—一个基于ARINC653的应用程序仿真调试工具

JL653是安装在PC机Windows操作系统上面的一层接插件,它能够真实地模拟ARINC653标准规定的功能性行为,从而可以供研发人员在PC机Windows环境下高效、快速的进行基于ARINC653的应用程序的开发、调试等。 JL653提供了ARINC 653 Part 1中要求的以下服务&…

每日刷题-6

目录 一、选择题 二、算法题 1.Fibonacci数列 2.合法括号序列判断 一、选择题 1、 解析:内联函数是一种可以提高函数执行效率的方法,它的原理是编译时在函数调用点直接展开函数体的代码,从而避免了函数调用的开销。 但是,内联函…

发布文章到wordpress

给朋友新建的wp网站,没有内容怎么办,总不能一篇篇的挨个写入吧。用wp提供的录入模块就可以了 参考 wp说明文档 获取docx内容保存到wp 资料有个docx文件,但文件格式混乱,好在有目录,可以基于目录,对文章分割,用正则拆分存入wp 首先用pandoc把docx转为md文件,速度较慢,…

EDA(Exploratory Data Analysis)探索性数据分析

EDA(Exploratory Data Analysis)中文名称为探索性数据分析,是为了在特征工程或模型开发之前对数据有个基本的了解。数据类型通常分为两类:连续类型和离散类型,特征类型不同,我们探索的内容也不同。 1. 特征类型 1.1 连续型特征 …

C语言——数据在内存中的存储_学习笔记

引言 在C语言——二进制/移位操作符/位操作符_学习笔记一文中有提到,数据在内存中是以二进制的形式存储的,也就是0和1; 而整数的二进制表示方法有三种,原码、反码和补码,文中也有所提及 而关于浮点数,浮点数…

在PHP8中向数组添加元素-PHP8知识详解

在php8中向数组添加元素有多种方法,在这里主要讲解几个常用的方法:使用方括号[]添加元素、使用array_unshift()函数,向数组的头部添加元素、使用array_push()函数,向数组的尾部添加元素、使用array_splice()函数添加元素。 1、使用…

【C++】类和对象(中下)

前言: 上一篇文章,我们了解了类的默认成员函数——构造函数、析构函数、拷贝构造函数,这篇我们让我们接着了解。 一、赋值运算符重载: 1.运算符重载: C为了增强代码的可读性引入了运算符重载,运算符重载是…

数据科学的文本技术 Text Technology(IR信息检索、搜索引擎)

一、文章摘要 1. 内容 * Introduction to IR and text processing, system components * Zipf, Heaps, and other text laws * Pre-processing: tokenization, normalisation, stemming, stopping. * Indexing: inverted index, boolean and proximity search * Evaluation m…

测试进阶知识之零日攻击的发现和防御

零日攻击是指针对软件或系统中未公开(或未被开发者知晓)的漏洞进行的攻击。这些漏洞被称为零日漏洞,因为在被公开之前,它们对开发者或安全研究人员来说是未知的,所以没有足够的时间进行防御或修复。 发现零日漏洞 发…

数据集成:数据挖掘的准备工作之一

⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ 🐴作者:秋无之地 🐴简介:CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作,主要擅长领域有:爬虫、后端、大数据…

清华大学 邓俊辉数据结构 关于哈希表的章节

本来以为没有 但是搜索hash 发现被叫做散列表 所以在9.3节就可以找到了

Keepalived+LVS高可用集群

目录 一、keepalived介绍: 二、keepalived工具介绍: (1)管理 LVS 负载均衡软件: (2)支持故障自动切换: (3)实现 LVS 负载调度器、节点服务器的高可用性&…

HTML5教程之移动端Web页面布局

一、什么是移动端项目 顾名思义,运行在移动端的项目就称为移动端项目。那什么是移动端呢,主要是指我们的一些手持设备,最具有代表性的就是我们日常使用的手机和平板,当然还包括一些其他便携设备,如智能手表&#xff0c…

LVS keepalived实现高可用负载群集

目录 1 Keepalived及其工作原理 1.1 Keepalived体系主要模块及其作用: 2 LVSKeepalived 高可用群集部署 2.1 配置负载调度器(主、备相同) 2.1.1 配置keeplived(主、备DR 服务器上都要设置) 2.1.2 启动 ipvsadm 服…

重新认识交叉编译

1. 我以前对交叉编译的认知 引用正点原子的话来讲就是: 说得对,但是不全面,直到最近项目中遇到了一个例子我才重新认识什么是交叉编译。 2. build/host/target的概念 参考: Cross-Compilation (automake) 参考: Specifying Target Triplets (Autocon…

javaee之黑马乐优商城3

异步查询工具axios(儿所以时) vue官方推荐的ajax请求框架 新增品牌页面 如何找到上面这个页面 下面这个页面里面的新增商品弹窗 上面就是请求路径与请求方式 那么请求参数是什么? brand对象,外加商品分类的id数组cids (这里其实不止就是添加…

腾讯mini项目-【指标监控服务重构】2023-07-31

今日已办 trace_id传播 关于如何使用 trace_id 创建 span 的思路 【暂未实现 & 测试】 调研 SpanProcessor 阅读源码的test 明日待办 根据 trace_id 创建 span,应该需要 parent span_id 才能有 trace 的树状 span 的关系

腾讯mini项目-【指标监控服务重构】2023-08-06

今日已办 feature/client_traces_profile 修改 consumer 4个阶段的 spankind将 profile 的 span 作为 root span,保持与 venus 的 follows from 的 link feature/profile-otelclient-metric 将 metric 部分使用新分支 push go.opentelemetry.io/otel/propagatio…

定时器类的编写与解析 —— TinyWebServer

定时器类的编写与解析 —— TinyWebServer 一、前言 定时器非常好写。就是链表加定时函数。搞懂他的作用就成。 定时器的作用是什么?什么是回调函数?用到的函数是什么? 二、问题回答 Ⅰ、定时器的作用是什么? 处理非活跃的连…