java怎么碰到异常跳过继续执行_Java异常处理很难吗?BAT大厂的架构师是怎么处理Java异常的?...

0c03c6793cff0d7a377afa8ce3671cf1.png

欢迎关注专栏《Java架构筑基》——专注于Java技术的研究与分享!

Java架构筑基​zhuanlan.zhihu.com
976a8b93ec3bbb1f18adef94486df1b0.png
  • Java架构筑基——专注于Java技术的研究与分享!
  • 后续文章将首发此专栏!
  • 欢迎各位Java工程师朋友投稿和关注
  • # 链接 Java程序员福利"常用资料分享"

异常是运行时在代码序列中引起的非正常状态。在不支持异常处理的计算机语言中,必须手动检查和处理错误,Java语言则采用面向对象的方式管理运行时错误

一、基础知识

Java异常是用来描述在一段代码中发生的异常情况的对象。当出现引起异常的情况时,就会创建用来表示异常的对象,并在引起异常的方法中抛出异常对象。方法可以选择自己处理异常或者传递异常交由其他方法来处理

Java异常处理通过五个关键字进行管理:try、catch、throw、throws、finally

在try代码快中封装可能发生异常的程序语句,对这些语句进行监视。如果在try代码块中发生异常,就会将异常抛出。代码使用catch来捕获异常,并可以定义一些方法来处理异常。系统生成的异常由Java运行时系统自动抛出。为了手动抛出异常,需要使用throw关键字。从方法中抛出的任何异常都必须通过一条throws子句进行指定。在try代码块结束之后必须执行的所有代码则需要放在finally代码块中

二、异常类型

所有异常类型都是内置类Throwable的子类,Throwable的两个子类将异常分为两个不同的分支。一个分支是Exception类,这个类既可以用于用户程序当前捕获的异常情况,也可以用于创建自定义异常类型的子类。另一个分支是Error类,该类定义了在常规环境下不希望由程序捕获的异常。Error类型的异常由Java运行时系统使用,以指示运行时系统本身发生了某些错误

三、未捕获的异常

没有被程序捕获的所有异常,最终都会交由Java运行时系统提供的默认处理程序捕获。默认处理程序会显示一个描述异常的字符串,输出异常发生的堆栈踪迹并终止程序

例如,运行如下代码:

public class Demo {public static void main(String[] args) {int a=2/0;}}

生成的异常信息:

Exception in thread "main" java.lang.ArithmeticException: / by zeroat Demo.main(Demo.java:5)

抛出的异常的类型是Exception的子类ArithmeticException,即算术异常,更具体地描述了发生的错误类型。Java提供了一些能与可能产生的各种运行时错误相匹配的内置异常类型

四、使用try和catch

进行主动的异常处理有两个优点:第一,语序允许修复错误;第二,阻止程序自动终止

为了主动处理运行时错误,可以在try代码块中封装希望监视的代码,之后通过catch子句指定希望捕获的异常类型。 例如,参照如下代码:

    public static void main(String[] args) {try{int a=10/0;System.out.println("输出语句1");}catch(ArithmeticException e){System.out.println("输出语句2");}System.out.println("输出语句3");}

输出结果是:

    输出语句2输出语句3

代码在进行除零操作时发生了异常,此时“输出语句1”将无法得到被调用的机会。一旦抛出异常,程序控制就会从try代码块中转移出来,进入catch代码块中。执行了catch语句后,就会继续运行整个try/catch代码块的下一行

五、多条catch子句

在有些情况下,一个代码块可能会引发多个异常。对于这种情况,需要指定两条或多条catch子句,用于捕获不同类型的异常。当抛出异常时,按顺序检查每条catch语句,执行类型和异常相匹配的第一条catch子句,忽略其他catch子句,并继续执行try/catch代码块后面的代码

需要注意的是,异常子类必须位于异常超类之前,因为使用了某个超类的catch语句会捕获这个超类及其所有子类的异常。因此,如果子类位于超类之后的话,永远也不会到达子类。不可到达的代码会被编译器提示错误

参照如下代码,通过Math的静态方法random来随机产生0和1两个随机数,生成的不同数值就会引发不同的异常,分别由不同的catch子句进行处理

    public static void main(String[] args) {    int random=(int) Math.round(Math.random());try{int a=10/random;int[] array={10};array[random]=1;}catch (ArithmeticException e) {System.out.println("ArithmeticException");}catch (ArrayIndexOutOfBoundsException e) {System.out.println("ArrayIndexOutOfBoundsException");}System.out.println("代码块结束");}

此外,也可以通过多重捕获的方式来使用相同的catch子句捕获两个或更多个异常。在catch子句中使用或运算符(|)分隔每个异常,每个多重捕获参数都被隐式地声明为final类型

    public static void main(String[] args) {    int random=(int) Math.round(Math.random());try{int a=10/random;int[] array={10};array[random]=1;}catch(ArithmeticException | ArrayIndexOutOfBoundsException e){System.out.println("两个异常之一");}}

六、throw

在之前的例子中,捕获的异常都是由Java运行时系统抛出的异常,可以通过throw语句显式地抛出异常

throw的一般形式如下所示:

throw ThrowableInstance 

ThrowableInstance必须是Throwable或其子类类型的对象。throw语句之后的执行流程会立即停止,所有的后续语句都不会执行,然后按顺序依次检查所有的catch语句,检查是否和异常类型相匹配。如果没有找到匹配的catch语句,那么默认的异常处理程序会终止程序并输出堆栈踪迹

例如,运行以下代码,将得到输出结果:“NullPointerException”

public class Demo {public static void demo(){throw new NullPointerException("NullPointer");}public static void main(String[] args) {try{demo();}catch (NullPointerException e) {System.out.println("NullPointerException");}}}

但如果catch子句的异常与throw抛出的异常类型不匹配时,异常将由Java默认的异常处理程序来处理

例如,运行以下代码:

public class Demo {public static void demo(){throw new NullPointerException("NullPointer");}public static void main(String[] args) {try{demo();}catch (ArrayIndexOutOfBoundsException e) {System.out.println("ArrayIndexOutOfBoundsException");}}}

运行结果是:

Exception in thread "main" java.lang.NullPointerException: NullPointerat Demo.demo(Demo.java:4)at Demo.main(Demo.java:9)

七、throws

如果方法可能引发自身不进行处理的异常,就必须通过throws关键字来向方法的调用者指明要抛出的异常类型。 方法可能抛出的所有异常都必须在throws子句中进行声明,否则将产生编译时错误

例如,参照以下代码,该程序试图抛出无法匹配的异常,因为程序没有指定throws子句来声明这一事实,所以程序无法编译

public class Demo {public static void demo(){throw new IllegalAccessException("IllegalAccess");}public static void main(String[] args) {demo();}}

为了使代码能够运行,需要将之进行如下修改

public class Demo {public static void demo() throws IllegalAccessException{throw new IllegalAccessException("IllegalAccess");}public static void main(String[] args) {try {demo();} catch (IllegalAccessException e) {System.out.println(e.getMessage());}}}

八、finally

当抛出异常后,方法的执行流程将不会按照原先的顺序进行,这对于某些方法来说是个问题。例如,如果在方法中打开了一个文件,我们并不希望因为抛出了异常导致关闭文件的代码被跳过而不执行。finally关键字就是来解决这种情况的。 使用finally可以创建一个代码块,该代码块会在执行try/catch代码块之后执行,且在执行try/catch代码块后面的代码之前执行。不管是否有异常抛出,都将执行finally代码块

只要方法从try/catch代码块内部返回到调用者,不管是通过未捕获的异常还是使用显式的返回语句,都会在方法返回之前执行finally子句

例如,如下的输出结果将是:2

public class Demo {public static int demo(){try{int a=10/0;System.out.println(a);}catch(Exception e){return 1;}finally {return 2;}}public static void main(String[] args) {System.out.println(demo());}}

九、链式异常

链式异常用于为异常关联另一个异常,第二个异常用于描述当前异常产生的原因。例如,某个方法从文件读取数值来作为除法运算的除数,由于发生了I/O错误导致获取到的数值是0,从而导致了ArithmeticException异常

如果想要让代码调用者知道背后的原因是I/O错误,使用链式异常就可以来处理这种情况以及其他存在多层异常的情况

为了使用链式异常,Throwable有两个构造函数和两个方法用于处理这种情况

两个构造函数:

    Throwable(Throwable cause)Throwable(String message, Throwable cause)

cause即是用于指定引发当前异常的背后原因,message则可以用于同时指定异常描述

两个方法:

    Throwable getCause()Throwable initCause(Throwable cause)

getCause() 方法用来返回引发当前异常的异常,如果不存在背后异常则返回null

initCause(Throwable cause) 方法将cause和明面上的异常关联到一起,并返回对异常的引用。因此可以在创建异常之后将异常和背后异常关联到一起。但是,背后异常只能设置一次,即initCause(Throwable cause) 方法只能调用一次。此外,如果通过构造函数设置了背后异常,也不能再使用该方法来设置背后异常了

例如,参照如下代码:

public class Demo {public static void demo(){NullPointerException nullPointerException=new NullPointerException("nullPointer");nullPointerException.initCause(new ArithmeticException("Arithmetic"));throw nullPointerException;}public static void main(String[] args) {try {demo();} catch (Exception e) {System.out.println(e.getMessage());System.out.println(e.getCause().getMessage());}}}

运行结果是:

nullPointer     
Arithmetic 

链式异常可以包含所需要的任意深度,但是,过长的异常链可能是一种不良的设计

# 链接 Java程序员福利"常用资料分享"

3aa74bb81d7a323c3a93213565c45188.png

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

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

相关文章

mysql 回滚之后抛出异常_在PHP中 开始事务后,程序抛出异常 没有执行commit也没有执行rollback mysql事务会回滚吗?...

网上有人说开启事务后 sql语句执行错误或程序出错 没有执行rollback的情况下,下一次运行就会自动commit程序出错不会回滚rollback但是也有人说抛出异常等 程序如果MySQL存在没有提交的事务,那么这时候 AUTOCOMMIT 自动提交的参数应该是为 0 的。不过如果…

mygeneration mysql_利用Mygeneration 自动生成maping文件和entity类文件

利用Mygeneration 自动生成maping文件和entity类文件Mygeneration下载要下载1.3.0.3版本, 默认支持mysql了,不用再安装mysql的驱动了。Template Code : 主要使用的模板代码,会实时展示在Template Source选项卡中Interface Code : 根据Templat…

mysql schema命名规范_数据库设计 命名及编码规范

http://blog.csdn.net/seusoftware/archive/2010/04/24/5524414.aspx引用一、综述命名和编码过程中,定义有意义的名称,以易于理解、方便书写为原则。(1)避免使用中文,尽量使用全拼音或全英文,以方便国际化;(2)避免拼音…

怎么检测mysql主从正常_使用pt-table-checksum检查主从复制是否正常

其实对于一个小小的DBA来说,有时候是无法避免这些问题的。于是我们就需要一个工具,来检查主从复制是否正常,是否出现了错误。pt-table-checksum。相关阅读:MySQL 主从复制事件校验 MySQL Replic…

java 自动类型_java类型自动转换

package com.kevin.basic;/** java类型自动转换方面的知识点* int类型 double类型 默认类型*/public class Test {/*** param args*/public static void main(String[] args) {// TODO Auto-generated method stub/* int类型是整数的默认类型。* (1)第一种:正确运行…

a java虚拟机_Java虚拟机

内存分配以及回收Java虚拟机运行时数据区,分为以下几个模块,包含所有线程共有的数据区和线程单独享有的数据区。程序计数器:字节码行号,通过这个计数器来选取下一条需要执行的指令,线程独有。虚拟机栈:线程…

java tostring的用处_JAVA的tostring()方法的作用是什么呢?

展开全部1.toString方法Object类具有一个toString()方法,你创建的每个类都会继承62616964757a686964616fe4b893e5b19e31333365666236该方法。它返回对象的一个String表示,并且对于调试非常有帮助。然而对于默认的toString()方法往往不能满足需…

java软件工程_java复习

计算机一些物理装置按系统结构的要求构成一个有机整体为计算机软件运行提供物质基础。计算机硬件:CPU、主板(motherboard)、内存(memory)、电源、主机箱、硬盘、显卡、键盘、鼠标、显示器等IO:input输入(鼠标键盘)、output输出(显示器音响)冯诺依曼体系结…

java getparametermap_重写getParameterMap后,报错 ,

想做个参数过滤功能,如何修改,或者其他实现方式ServletExcludeHadler类在HttpServletRequestWrapper类里重写了getParameterMap现在报错java.lang.ClassCastException: org.apache.catalina.util.ParameterMap cannot be cast to java.util.HashMapat co…

java 抽样_Java编程实现二项分布的采样或抽样实例代码

本文研究的主要是Java编程实现二项分布的采样或抽样,下面是详细实现代码。如下程序为n100,p0.9的二项分布采样,共采样10000次package function;import org.apache.commons.math3.distribution.BetaDistribution;import org.apache.commons.ma…

java中什么是 伪共享_【Java】聊聊多线程中的伪共享现象

首页专栏java文章详情0聊聊多线程中的伪共享现象小强大人发布于 1 月 27 日什么是伪共享?讲伪共享之前,让我们先乘坐时光机,回到大学课堂,来重温下计算机组成原理的基础知识。我们知道,CPU和内存的运行速度相差很大&am…

新闻资讯java开发_新闻资讯app开发的功能与意义

获取新闻的目的因人而异,但对获取新闻的需求是一样的。现在是移动互联网的时代。人们不再想依靠传统的手段,而把便利作为获取服务的核心。因此,开发新闻咨询app是必要的。其到来不仅意味着获得新闻登上新的阶梯,还因为画出了圆满的…

php实时上传多张图片,PHP实现多张图片上传预览功能

PHP实现多张图片上传预览功能,支持左右移动图片切换位置、删除图片,限制图片上传的数量等-向左移动图片function reverse_left(obj) {var obj_li obj.parents("li");var obj_prev obj_li.prev("li");if (obj_prev.hasClass("…

centos php 默认安装目录,centos系统中的软件安装目录在哪

centos系统中软件的默认安装目录一般在/usr/local或者/opt中。我们还可以通过whereis命令来查看软件的实际安装路径。命令:whereis功能介绍:在特定目录中查找符合条件的文件。这些文件的烈性应属于原始代码,二进制文件,或是帮助文…

php atlas,apache atlas是什么

Atlas是一组可伸缩和可扩展的核心基础治理服务——使企业能够有效和高效地满足Hadoop中的遵从性需求,并允许与整个企业数据生态系统进行集成。Apache Atlas为组织提供开放的元数据管理和治理能力,以建立其数据资产的目录,对这些资产进行分类和…

php2588,搞清楚一下必胜2588z和2582z哪个好点?都有些什么区别?内幕评测分析

这二个必胜2588z和2582z区别不是很大的哈,款式和配置是差不多的,只是必胜2582Z 2052Z更强一些,看个人需要吧,不过家用的话,这两款都是可以的,我自己用的是必胜2582Z 2052Z,款式多大气的&#xf…

超表面透镜相位matlab,基于超透镜的小F数大景深镜头的设计方法及应用与流程...

本发明涉及基于超透镜的小f数大景深镜头的设计方法及应用。背景技术:监控系统中采用的透镜往往要求具有尽量高的成像分辨率和尽量大的景深,通常情况下,高分辨率的透镜一般具有较小f数,大的景深又要求焦距较短。但是利用传统透镜的…

php等级证书,php银行开放平台接口1:php 对cer证书处理

做一个银行接口要进行证书解析和签名,然后验证获token银行开放平台提供了2个证书public.cer 证书 :里面只有公钥200090491595.pfx证书 :里面有公钥和私钥这里专门做public.cer的说明和处理,.cer为扩展的证书,就是一个x…

oracle 9i hwm,Oracle 10g HWM原理及性能优化

摘 要: HWM(High Water Mark)是表中已经使用过的存储空间与未使用过的存储空间之间的分界线,HWM对全表扫描的性能有非常大的影响。当全表扫描时,Oracle会读取HWM下所有的块,即使这些块中有很多是空块,空块的存在,也即是…

五款救急的linux文件恢复软件,五款救急的Linux文件恢复软件

BKJIA快译】文件有备份,啥子也不愁!文件无备份,啥子也白搭。但是,面对突如其来的悲剧,文件恢复软件来帮忙时可以尽量最小化减小损失。下面Linux用户需知的5款文件恢复软件:#1,Ddrescue主页&…