Java的异常处理机制

2023-11-05

一、什么是java异常?

java异常指在程序运行时可能出现的一些错误,如:文件找不到、网络连接失败、非法参数等。异常是一个事件,它发生在程序运行期间,中断了正在执行的程序的正常指令流。Java通过API中Throwable类的众多子类描述各种不同的异常。因而,Java异常都是对象,是Throwable子类的实例,描述了出现在一段编码中的错误条件。当条件生成时,错误将引发异常。

Java异常类的层次结构图,如下所示(盗的图):

Java所有异常类都是 Throwable的子类。它包括Java异常处理的两个重要子类:Error和Exception.

Error:Error及其子类用来描述Java运行系统中的内部错误以及资源耗尽的错误,是程序无法处理的错误,这类错误比较严重。这类的大多数错误与代码编写者执行的操作无关,如,运行代码时,JVM(Java虚拟机)出现的问题,例如,Java虚拟机运行错误(Virtual MachineError),当 JVM 不再有继续执行操作所需的内存资源时,将出现 OutOfMemoryError。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止。 这些错误是不可查的,因为它们在应用程序的控制和处理能力之外,而且绝大多数是程序运行时不允许出现的状况。对于设计合理的应用程序来说,即使确实发生了错误,本质上也不应该试图去处理它所引起的异常状况。 

Exception:可以通过捕捉处理使程序继续执行,是程序自身可以处理的异常,也称为非致命性异常类。根据错误发生原因可分为RuntimeException异常和除RunTimeException之外的异常,如IOException异常。RuntimeException 类及其子类表示“JVM 常用操作”引发的错误。例如,若试图使用空值对象引用、除数为零或数组越界,则分别引发运行时异常(NullPointerException、ArithmeticException)和 ArrayIndexOutOfBoundException。 

简单来说:异常与错误的区别是:异常可以通过程序自身捕捉处理,而错误是程序自身无法处理的。

Java异常包括Exception类和Error类,其可分为可查异常和不可查异常:

可查异常:编译器要求必须处理的异常,这类异常的发生在一定程度上是可以预计的,而且这类异常一旦发生,就必须采用某种方式进行处理。除了RuntimeException及其子类以外的其它异常类都属于可查异常。这种异常的特点是Java编译器会检查它,也就是说,出现这种异常,要么用try-catch语句捕捉它,要么用throws语句声明抛出它,否则编译不通过。

不可查异常:编译器不要求强制处理的异常,包括运行时异常(RuntimeException与其子类)和错误(Error) 。

Exception 异常又可分为两大类:运行时异常和非运行时异常(编译异常)。程序中应当尽可能去处理这些异常。        

运行时异常:RuntimeException类及其子类异常,如NullPointerException(空指针异常)、IndexOutOfBoundsException(下标越界异常)等,这些异常是不可查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。       

运行时异常的特点:Java编译器不会检查它,也就是说,当程序中出现这类异常时,也会编译通过。        

非运行时异常 (编译异常):是RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException、SQLException等以及用户自定义的Exception异常,一般情况下不自定义检查异常。 

二、异常处理机制

 在 Java 应用程序中,异常处理机制为:抛出异常,捕捉异常。        

抛出异常:当一个方法出现错误引发异常时,方法创建异常对象并交付运行时系统,异常对象中包含了异常类型和异常出现时的程序状态等异常信息。运行时系统负责寻找处置异常的代码并执行。        

捕捉异常:在方法抛出异常之后,运行时系统将转为寻找合适的异常处理器(exception handler)。潜在的异常处理器是异常发生时依次存留在调用栈中的方法的集合。当异常处理器所能处理的异常类型与方法抛出的异常类型相符时,即为合适的异常处理器。运行时系统从发生异常的方法开始,依次回查调用栈中的方法,直至找到含有合适异常处理器的方法并执行。当运行时系统遍历调用栈而未找到合适的异常处理器,则运行时系统终止。同时,意味着Java程序的终止。        

对于运行时异常、错误或可查异常,Java技术所要求的异常处理方式有所不同。        

由于运行时异常的不可查性,为了更合理、更容易地实现应用程序,Java规定,运行时异常将由Java运行时系统自动抛出,允许应用程序忽略运行时异常。        

对于方法运行中可能出现的Error,当运行方法不欲捕捉时,Java允许该方法不做任何抛出声明。因为,大多数Error异常属于永远不能被允许发生的状况,也属于合理的应用程序不该捕捉的异常。        

对于所有的可查异常,Java规定:一个方法必须捕捉,或者声明抛出方法之外。也就是说,当一个方法选择不捕捉可查异常时,它必须声明将抛出异常。        

能够捕捉异常的方法,需要提供相符类型的异常处理器。所捕捉的异常,可能是由于自身语句所引发并抛出的异常,也可能是由某个调用的方法或者Java运行时 系统等抛出的异常。也就是说,一个方法所能捕捉的异常,一定是Java代码在某处所抛出的异常。简单地说,异常总是先被抛出,后被捕捉的。          

任何Java代码都可以抛出异常,如:自己编写的代码、来自Java开发环境包中代码,或者Java运行时系统。无论是谁,都可以通过Java的throw语句抛出异常。从方法中抛出的任何异常都必须使用throws子句。捕捉异常通过try-catch语句或者try-catch-finally语句实现。          

总体来说,Java规定:对于可查异常必须捕捉、或者声明抛出。允许忽略不可查的RuntimeException和Error。  

抛出异常的方法:throws和throw

throws:通常被用在声明方法时,用来指定方法可能抛出的异常,多个异常可使用逗号分隔。throws关键字将异常抛给上一级,如果不想处理该异常,可以继续向上抛出,但最终要有能够处理该异常的代码。

throw:通常用在方法体中或者用来抛出用户自定义异常,并且抛出一个异常对象。程序在执行到throw语句时立即停止,如果要捕捉throw抛出的异常,则必须使用try-catch语句块或者try-catch-finally语句。

例1:throws方法抛出异常

public class Shoot {
    static void pop()throws NegativeArraySizeException{
    	int[] arr = new int[-3];
    }
	public static void main(String[] args) {
		 try{
			 pop();
		 }catch(NegativeArraySizeException e){
			 System.out.println("pop()方法抛出的异常");
		 }
	}

}

运行结果:

                 

例2:throw方法抛出异常

public class TestException {
	public static void main(String[] args) {
		int a = 6;
		int b = 0;
		try {  
			
			if (b == 0) throw new ArithmeticException(); // 通过throw语句抛出异常
			System.out.println("a/b的值是:" + a / b);
		}
		catch (ArithmeticException e) { // catch捕捉异常
			System.out.println("程序出现异常,变量b不能为0。");
		}
		System.out.println("程序正常结束。");
	}
}

 运行结果:

                 

 三、理解try-catch-finally语句

首先,我们来看一个例子(网上找的),大家想想运行之后的结果是什么?

package Exception;

public class exception4 {
	public exception4() {
	}
 
	boolean testEx() throws Exception {
		boolean ret = true;
		try {
			ret = testEx1();
		} catch (Exception e) {
			System.out.println("testEx, catch exception");
			ret = false;
			throw e;
		} finally {
			System.out.println("testEx, finally; return value=" + ret);
			return ret;
		}
	}
 
	boolean testEx1() throws Exception {
		boolean ret = true;
		try {
			ret = testEx2();
			if (!ret) {
				return false;
			}
			System.out.println("testEx1, at the end of try");
			return ret;
		} catch (Exception e) {
			System.out.println("testEx1, catch exception");
			ret = false;
			throw e;
		} finally {
			System.out.println("testEx1, finally; return value=" + ret);
			return ret;
		}
	}
 
	boolean testEx2() throws Exception {
		boolean ret = true;
		try {
			int b = 12;
			int c;
			for (int i = 2; i >= -2; i--) {
				c = b / i;
				System.out.println("i=" + i);
			}
			return true;
		} catch (Exception e) {
			System.out.println("testEx2, catch exception");
			ret = false;
			throw e;
		} finally {
			System.out.println("testEx2, finally; return value=" + ret);
			return ret;
		}
	}
 
	public static void main(String[] args) {
		exception4 testException1 = new exception4();
		try {
			testException1.testEx();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

运行结果:

                  

哈哈!!!你的答案是否与正确答案一样呢? 

大家可能刚看上去有这么多的try-catch-finally语句,感觉会比较懵!但实际上try-catch-finally语句理解很简单,只要牢记这些规则就好了:

对于try-catch-finally语句:先执行try 块中的代码,如果正常运行没有发生异常则执行完后执行finally 代码块中的代码;如若在try 中发生异常且被catch 捕捉到则执行catch 中的代码块,然后执行finally 块中的代码;

这样讲,大家都明白了吧,是不是很简单!!!

但也存在以下4种特殊情况,finally块不会被执行:

      在前面的代码中使用了System.exit()退出程序;

      在finally语句块中发生异常;

      程序所在的线程死亡;

      关闭CPU。

想知道更多详细的内容,请参考如下链接地址:

https://blog.csdn.net/hguisu/article/details/6155636?utm_source=copy

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java的异常处理机制 的相关文章

  • java中监视目录变化

    我正在使用 WatchService 来监视目录中的更改 特别是目录中新文件的创建 下面是我的代码 package watcher import java nio file import static java nio file Stand
  • 如何在由子控件组成的 SWT 复合材料上跟踪鼠标?

    我创建了自己的控件 我想跟踪鼠标并添加一个MouseTrackListener 很遗憾MouseEnter and MouseLeave当鼠标移动到我的合成部分 即标签和按钮 上时 也会生成事件 Mouse enter mouse ente
  • 与 Eclipse 中的 Java Content Assist 交互

    作为我的插件项目的一部分 我正在考虑与 Eclipse 在 Java 文件上显示的内容辅助列表进行交互 我正在尝试根据一些外部数据对列表进行重新排序 我看过一些有关创建新内容辅助的教程 但没有看到有关更改现有内容辅助的教程 这可能吗 如果是
  • 如何在 JPQL 或 HQL 中进行限制查询?

    在 Hibernate 3 中 有没有办法在 HQL 中执行相当于以下 MySQL 限制的操作 select from a table order by a table column desc limit 0 20 如果可能的话 我不想使用
  • 将巨大的模式编译成Java

    有两个主要工具提供了将 XSD 模式编译为 Java 的方法 xmlbeans 和 JAXB 问题是 XSD 模式确实很大 30MB 的 XML 文件 大部分模式在我的项目中没有使用 所以我可以注释掉大部分代码 但这不是一个好的解决方案 目
  • 提供节点名或服务名,或未知 Java

    最近我尝试运行我的 Java 项目 每当我运行它并将其打开到我得到的服务器地址时 Unable to determine host name java net UnknownHostException Caused by java net
  • 在 Java 中如何找出哪个对象打开了文件?

    我需要找出答案哪个对象在我的 Java 应用程序中打开了一个文件 这是为了调试 因此欢迎使用工具或实用程序 如果发现哪个对象太具体了 这class也会很有帮助 这可能很棘手 您可以从使用分析器开始 例如VisualVM http visua
  • Android 无法解析日期异常

    当尝试解析发送到我的 Android 客户端的日期字符串时 我得到一个无法解析的日期 这是例外 java text ParseException 无法解析的日期 2018 09 18T00 00 00Z 位于 偏移量 19 在 java t
  • 如何在 ant 中为 junit 测试设置 file.encoding?

    我还没有完全完成file encoding 和 ant https stackoverflow com questions 1339352 how do i set dfile encoding within ants build xml
  • 从jar中获取资源

    我有包含文件的 jar myJar res endingRule txt myJar wordcalculator merger Marge class 在 Marge java 中我有代码 private static final Str
  • 如何在.NET中使用java.util.zip.Deflater解压缩放气流?

    之后我有一个转储java util zip Deflater 可以确认它是有效的 因为 Java 的Inflater打开它很好 并且需要在 NET中打开它 byte content ReadSample sampleName var inp
  • Jetty、websocket、java.lang.RuntimeException:无法加载平台配置器

    我尝试在 Endpoint 中获取 http 会话 我遵循了这个建议https stackoverflow com a 17994303 https stackoverflow com a 17994303 这就是我这样做的原因 publi
  • 在 Java 中获取并存储子进程的输出

    我正在做一些需要我开始子处理 命令提示符 并在其上执行一些命令的事情 我需要从子进程获取输出并将其存储在文件或字符串中 这是我到目前为止所做的 但它不起作用 public static void main String args try R
  • 如何区分从 Saxon XPathSelector 返回的属性节点和元素节点

    给定 XML
  • 轻松的反应

    我有一个与这里描述的类似的案例 动态更改RESTEasy服务返回类型 https stackoverflow com questions 3786781 dynamically change resteasy service return
  • Spring @Cacheable 和 @Async 注解

    我需要缓存一些异步计算的结果 具体来说 为了克服这个问题 我尝试使用 Spring 4 3 缓存和异步计算功能 作为示例 我们采用以下代码 Service class AsyncService Async Cacheable users C
  • 列表过滤器内的 Java 8 lambda 列表

    示例 JSON id 1 products id 333 status Active id 222 status Inactive id 111 status Active id 2 products id 6 status Active
  • java 中的蓝牙 (J2SE)

    我是蓝牙新手 这就是我想做的事情 我想获取连接到我的电脑上的蓝牙的设备信息并将该信息写入文件中 我应该使用哪个 api 以及如何实现 我遇到了 bluecove 但经过几次搜索 我发现 bluecove 不能在 64 位电脑上运行 我现在应
  • Java 11 - 将 Spring @PostConstruct 替换为 afterPropertiesSet 或使用 initMethod

    我正在使用 spring 应用程序 有时会使用 PostConstruct用于代码和测试中的设置 看来注释将被排除在外Java 11 https www baeldung com spring postconstruct predestro
  • Java 和/C++ 在多线程方面的差异

    我读过一些提示 多线程实现很大程度上取决于您正在使用的目标操作系统 操作系统最终提供了多线程能力 比如Linux有POSIX标准实现 而windows32有另一种方式 但我想知道编程语言水平的主要不同 C似乎为同步提供了更多选择 例如互斥锁

随机推荐

  • UE4_UStruct 遍历

    一个结构体中存在一个Val变量 Val变量的类型是FVector4 想从c 层面去遍历获得Val的值 上图是很早之前的一个Property继承关系图 当然 在4 25UProperty被FProperty夺笋 好处呢 见下 没有继承UObj
  • etcd的使用

    启动etcd服务 启动etcd时最主要的是需要准备两个没有使用过的端口 这两个端口一个用于etcd之间同步信息 一个用于etcd向客户端提供服务的端口 因此启动单个etcd节点 只需按照如下命令行输入即可 server name myetc
  • sigmoid & logistic

    1 吴恩达老师视频中说sigmoid函数就是logistic函数 2 查阅复旦大学邱锡鹏老师关于深度学习的书 在第四章中写道 Sigmoid型函数是指一类S型曲线函数 为两端饱和函数 常用的Sigmoid型函数有Logistic函数和Tan
  • OpenPose笔记——windows 10下,自编译openpose代码(vs下能跑了,pythonAPI也能使了)

    简直太可怕了 遇到N多的问题 我觉有必要写下来记录一下 我自己编译了四五天 编译了10几次 夭寿哦 缺好多好多东西 给大家讲一下具体步骤 一 准备工作 准备工作当然是各种环境 1 至少VS2015 以上的版本 2 CMake Gui 注意
  • 问题定义过程

    问题定义过程由四步组成 确立需求 证明需求 理解问题和它的上下文和问题陈述 这个模型的主要优点是能够帮助你确定和理解问题的细节 帮助你了解组织的使命和战略在问题解决过程中的的重要性 从这里你可以确定问题是否值得努力寻求解决方案 只有明白了问
  • 自顶向下 逐步求精

    将复杂的大问题分解为相对简单的小问题 找出每个问题的关键 重点所在 然后用精确的思维定性 定量地去 描述问题 其核心本质是 分解 自顶向下 top down 的分析算法通过在最左推导中描述出各个步骤来分析记号串输入 之所以称这样的算法为自顶
  • 埋点系统:详解设计埋点过程中的“who when where how what”

    上次写了一篇 如何用数据驱动产品迭代 其中提到了一点设计埋点的方法 很多朋友留言说需要设计埋点的指南 像我这种从来不拒需求的人 这两天下班闲下来之后就整理了一下埋点设计的一些知识 希望能有所帮助 在诸多招聘 JD 中提到的数据分析能力 主要
  • 使用raspberry pi pico 制作红绿灯

    需要的东西 一块面包版 一块raspberry pi pico 红绿黄led灯各一颗 220欧电阻3只 若干线 编程软件 thonny 操作系统 deepin 23 结果展示 使用raspberry pi pico 制作红绿灯 from m
  • 金山云服务器异常,金山云-文档中心-金山云告诉你:找不到服务器或dns错误怎么办...

    我们在用电脑 会经常使用浏览器 不少人经常在浏览网页时候突然跳出一个提示 上面显示 找不到服器 或 dns错误 下面 给大家分享找不到服务器或dns错误的解决经验 1 病毒所致 如果你电脑中了病毒 让你的DNS被劫持 比如自己的浏览器主页被
  • 【毕业设计】基于PLC的十字路口交通灯控制系统设计【仿真+源码+论文】

    摘 要 本次设计的课题是基于PLC的十字路口交通灯控制系统设计 传统的十字路口交通灯多采用单片机集成电路作为控制系统 单片机系统虽然在功能上能够实现十字路口交通灯的各种控制需求 但是单片机控制系统在设计时需要数字电路与模拟电路的完美结合 这
  • 基于跳表实现的轻量级KV存储引擎 项目总结

    参考 https github com youngyangyang04 Skiplist CPP 项目介绍 KV存储引擎 众所周知 非关系型数据库redis 以及levedb rockdb其核心存储引擎的数据结构就是跳表 本项目就是基于跳表
  • 5.0 Vue中使用webpack

    文章目录 webpack的基本使用 webpack中的插件 webpack打包发布 Source Map 注意 在实际开发中我们并不需要自己配置 webpack webpack中 的用法 在Chrome浏览器中安装vue devtools调
  • QT书籍分享——最全资料汇总

    QT从入门到精通 学习路线 市面上QT学习的书籍也挺多的 今天从学习路径上给大家一一盘点一下 并附上相关链接 大家可以根据需求下载哦 1 语言基础学习 学习QT最最最基础的当然是语言学习了 可以选择C 语言 也可以选择Python语言 C
  • 佛祖保佑,永无bug——springboot项目启动图案的修改方法

    在resources目录 与application yml文件同级目录 下创建banner txt文件 将下面的代码复制进去就好了 AnsiColor BRIGHT YELLOW ooOoo o8888888o
  • 动态规划-各种题型及思路整理(自用笔记,大神绕道)

    目录 简介 分类 基本思想 基本思路 状态转移方程 适用条件 一句话总结 应用 前缀和思想 简介 动态规划 dynamic programming 简称dp 是运筹学的一个分支 是求解决策过程 decision process 最优化的数学
  • 21天学习挑战赛——Python操作MySQL和SqlServer

    目录 1 pymysql模块 2 pymysql模块使用说明 2 1 pymysql操作流程图 2 2 创建连接对象 2 3 获取游标对象 2 4 用法举例 2 4 1 获取一条数据 6 4 2 获取多条数据 6 4 3 对数据进行增删改操
  • 未来社交媒体的变革者

    近日 Meta宣布了其认可的七大社交媒体趋势 这些趋势代表了未来社交媒体发展的核心方向 这些趋势中 生成式AI AR VR营销等引人注目的技术入选 预示着我们即将迎来全新的社交媒体时代 一 生成式AI 像人一样理解并回应 近年来 生成式AI
  • linux 非root用户 安装pyscipopt

    前提 实验室的服务器 我没有root权限 1 尝试用conda方法onda install channel conda forge pyscipopt 出现未知错误 搜遍百度谷歌stackoverflow都没有找到有人和我一样的问题 不知道
  • 基于Java的贪吃蛇小游戏

    一 开发思路 设定一个一定大小的且大小不可变的游戏窗口 在创建的窗口上绘制游戏的基本面板样式 使用提前保存的素材图标绘制一条静态的小蛇 使小蛇能够移动 实际只需蛇头坐标移动 每节身体覆盖前一节身体坐标 设置定时器Timer timer ne
  • Java的异常处理机制

    一 什么是java异常 java异常指在程序运行时可能出现的一些错误 如 文件找不到 网络连接失败 非法参数等 异常是一个事件 它发生在程序运行期间 中断了正在执行的程序的正常指令流 Java通过API中Throwable类的众多子类描述各