在我们日常编程中,异常处理是必不可少的,异常处理是否得当关系到程序的健壮性和后续维护成本。

试想一下,如果一个项目从头到尾没有考虑过异常处理,当程序出错从哪里寻找出错的根源?但是如果一个项目异常处理设计地过多,又会严重影响到代码质量以及程序的性能。因此,如何高效简洁地设计异常处理是一门艺术,今天我们来讲解一下。

1、什么是异常

异常Exception,就是非正常情况。比如常见的:数组越界异常、内存溢出异常、空指针异常等。在我们编写程序的过程中错误会时常发生,包括编译期间和运行期间的错误,在编译期间出现的错误有编译器帮助我们一起修正,然而运行期间的错误便不是编译器力所能及了,并且运行期间的错误往往是难以预料的。假若程序在运行期间出现了错误,如果置之不理,程序便会终止或直接导致系统崩溃,显然这是不行的。

那么,我们如何对运行期间出现的错误进行处理和补救呢?Java提供了一套异常处理机制,通过异常机制来处理程序运行期间出现的错误。通过异常机制,我们可以更好地提升程序的健壮性。

我们看下Jdk文档:

总结下,异常类的结构层次图如下图所示:

在Java中异常被当做对象来处理,根类是java.lang.Throwable类,在Java中定义了很多异常类(如OutOfMemoryError、NullPointerException、IndexOutOfBoundsException等),这些异常类分为两大类:Error和Exception。

Error是无法处理的异常,比如OutOfMemoryError,一般发生这种异常,JVM会选择终止程序。因此我们编写程序时不需要关心这类异常。

Exception,也就是我们经常见到的一些异常情况,比如NullPointerException、IndexOutOfBoundsException,这些异常是我们可以处理的异常。Exception类的异常包括checked exception和unchecked exception。

unchecked exception(非检查异常),也称运行时异常:都是RuntimeException类及其子类异常,如NullPointerException、IndexOutOfBoundsException等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。运行时Java编译器不会去检查该类异常,也就是说,当程序中可能出现这类异常,即使没有用try-catch语句捕获它,也没有用throws子句声明抛出它,也会编译通过。

checked exception(检查异常),也称非运行时异常 (编译异常):是RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException、SQLException等。

2、Java中如何处理异常

① 用try、catch捕获异常

可能发生异常的代码块用try{}括上,一旦发生异常,异常便会被catch捕获到(异常需要和catch块中的参数匹配上,发生的异常为catch块中的参数子类或本身则匹配上),然后在catch块中进行异常处理。

② 用throws向上层抛出异常

createFile方法中并没有捕获异常,而是用throws关键字声明抛出异常,即告知这个方法的调用者此方法可能会抛出IOException。那么在main方法中调用createFile方法的时候,采用try…catch块进行了异常捕获处理。

注:如果抛出的异常是非运行时异常(checked exception),此方法的调用者必须显示地用try…catch块进行捕获或者继续向上层抛出异常。如果抛出的异常是运行时异常,此方法的调用者可以选择地进行异常捕获处理。

③ 手动用throw向上层抛出异常

手动抛出了一个ArrayIndexOutOfBoundsException,上层调用的方法main来进行处理这个异常。

注:如果抛出的异常是非运行时异常(checked exception),此方法的调用者必须显示地用try…catch块进行捕获或者继续向上层抛出异常。如果抛出的异常是运行时异常,此方法的调用者可以选择地进行异常捕获处理。

3、运用try,catch,finally,throws,throw五个关键字

① try,catch,finally

try关键字用来包围可能会出现异常的逻辑代码,它单独无法使用,必须配合catch或者finally使用。Java编译器允许的组合使用形式只有以下三种形式:

try…catch…;try…finally…;try…catch…finally…

当然catch块可以有多个,注意try块只能有一个,finally块是可选的(但是最多只能有一个finally块)。三个块执行的顺序为try—>catch—>finally。

当然如果没有发生异常,则catch块不会执行。但是finally块无论在什么情况下都是会执行的(这点要非常注意,因此多数情况下,都会将释放资源的操作放在finally块中进行)。

在有多个catch块的时候,是按照catch块的先后顺序进行匹配的,一旦异常类型被一个catch块匹配,则不会与后面的catch块进行匹配。

在使用try…catch…finally块的时候,注意千万不要在finally块中使用return,因为finally中的return会覆盖已有的返回值。看下面例子:

输出结果,文件没有找到,抛出FileNotFoundException异常,执行finally块,正常返回2。

接下来把//return “4”;的注释去掉,再次运行,输出结果,我们看到finally的返回值4覆盖了catch块的返回值2。因此如果方法有返回值,切忌不要在finally中使用return,这样会使得程序结构变得混乱。

② throws和thow关键字

1)throws出现在方法的声明中,表示该方法可能会抛出的异常,然后交给上层调用它的方法程序处理,throws后面允许跟着多个异常类型;

2)一般会用于程序出现某种逻辑时程序员主动抛出某种特定类型的异常。throw只会出现在方法体中,当方法在执行过程中遇到异常情况时,将异常信息封装为异常对象,然后throw出去。

4、子类进行方法重写的时候,如何声明抛出异常

看代码:

从上面四个图,可以得出:

如果抛出的是RuntimeException类型的异常,Java编译器不会去检查它,所以在子类和父类中使用它都没有关系。

如果不是RuntimeException类型的异常,子类不能抛出比父类范围更广的异常。

5、几点建议

① 只在必要使用异常的地方才使用异常,不要用异常去控制程序的流程

谨慎地使用异常,异常捕获的代价非常高昂,异常使用过多会严重影响程序的性能。如果在程序中能够用if语句和Boolean变量来进行逻辑判断,那么尽量减少异常的使用,从而避免不必要的异常捕获和处理。

② 切忌使用空catch块

在捕获了异常之后什么都不做,相当于忽略了这个异常。千万不要使用空的catch块,空的catch块意味着你在程序中隐藏了错误和异常,并且很可能导致程序出现不可控的执行结果。最好用Log日志将该异常进行记录,以便日后方便更新和维护。

③ 有多个catch块时,需要注意catch块之间的顺序

多个catch块应该按照先子类后父类的顺序排列。如果先父类后子类排列,则后面的子类catch块不会执行到。

④ 异常处理尽量放在高层进行

尽量将异常统一抛给上层调用者,由上层调用者统一之时如何进行处理。如果在每个出现异常的地方都直接进行处理,会导致程序异常处理流程混乱,不利于后期维护和异常错误排查。由上层统一进行处理会使得整个程序的流程清晰易懂。

⑤ 在finally中释放资源

如果有使用文件读取、网络操作以及数据库操作等,记得在finally中释放资源。这样不仅会使得程序占用更少的资源,也会避免不必要的由于资源未释放而发生的异常情况。

欢迎小伙伴们留言交流~~

java方法被编译器调用_我异常了,快来捕获我,Java异常简述相关推荐

  1. java方法区内存泄露_深入理解java虚拟机-第二章:java内存区域与内存泄露异常...

    2.1概述: java将内存的管理(主要是回收工作),交由jvm管理,确实很省事,但是一点jvm因内存出现问题,排查起来将会很困难,为了能够成为独当一面的大牛呢,自然要了解vm是怎么去使用内存的. 2 ...

  2. java方法定义 与调用_Java方法的定义及调用

    Java方法的定义及调用 通过以上内容的学习,可以看出方法是一段可以完成某个特定功能的并且可以被重复利用的代码片段.接下来我们来学习一下方法应该怎么定义以及怎么调用. 定义/声明方法的语法格式如下所示 ...

  3. java方法区对象类型_浅谈Java内存区域与对象创建过程

    一.java内存区域 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有的区域则 ...

  4. Java方法创建及调用--------06

    一.静态方法 1.1含义 特定功能的代码块 1.2好处 减少代码的冗余,提高了代码的可读性和可维护性 1.3语法结构 访问修饰符 static 返回值类型 方法名(参数列表){            ...

  5. 【Android NDK 开发】JNI 方法解析 ( C/C++ 调用 Java 方法 | 函数签名 | 调用对象方法 | 调用静态方法 )

    文章目录 I . 调用 Java 方法流程 II . 获取 jclass 对象 ( GetObjectClass ) III . 获取 jclass 对象 ( FindClass ) IV . JNI ...

  6. JAVA 方法定义及调用

    1.方法 方法是实现某个功能的一组语句,通常将常用的功能写成一个方法(类中的方法). 方法能实现代码的模块化重用. 方法相当于函数,类似于加工厂.参数=原材料:方法体=加工:返回值(return)=出 ...

  7. java二级考试真题_计算机等级考试真题2(JAVA)

    1. D (A)类属于JAVA语言的引用数据类型. (B)接口属于JAVA语言的引用数据类型. (C)数组属于JAVA语言的引用数据类型. (D)double不属于JAVA语言的引用数据类型. 2. ...

  8. java 关闭阻塞线程池_如果优雅地关闭ExecutorService提供的java线程池

    每一个线程都会占用系统资源,因此线程池的关闭与清理同样重要,本文介绍我们如何优雅地关闭线程池. 一. ExecutorService中关闭线程池的方法 1. shutdown() 停止接收新任务,原来 ...

  9. java paint方法哪个周期调用_关于一段java程序的小问题,paint函数是什么时候执行的,没有调用啊...

    Java语言:高亮代码由发芽网提供01packagexline;020304importjavax.swing.*;05importjava.awt.*;0607publicclassDrawLine ...

最新文章

  1. 网站建设中购买虚拟主机重要参数有哪些?
  2. 解决update-apt-xapi占用资源过高的问题
  3. [云炬创业基础笔记]第九章企业的法律形态测试6
  4. boost::math::quadrature::exp_sinh用法的测试程序
  5. 三次样条插值之三对角矩阵算法
  6. 机器学习基础:逻辑回归(Machine Learning Fundamentals: Logistic Regression)
  7. Samba通过ad域进行认证并限制空间大小
  8. TCP/IP 协议大致的概念
  9. 主机overlay和网络overlay_边缘计算中kubernetes网络能大一统吗?
  10. cad放大_如何玩转CAD看图?1分钟,一款完全免费的高效软件,解决所有看图
  11. Jade模板引擎教程
  12. 人工智能产品经理最佳实践
  13. 用计算机软件绘制思维导图,一款简单好用的在线免费思维导图制作工具
  14. rebase操作使用方法
  15. 用计算机弹我们不一样谱子,我们不一样钢琴谱
  16. 苹果自带地图定位 经纬度
  17. iOS二维码生成及扫码
  18. 用C语言给孩子水果英语早教,幼儿英语早教水果,12种水果怎么读英语?
  19. SL651-2014 《水文监测数据通信规约》 人工置数详解
  20. linux 查看python路径

热门文章

  1. ansible的命令操作模块6
  2. Delphi XE 10.1 Can't bind address: Address already in use. Exiting.
  3. Hadoop问题:启动hadoop 2.6遇到的datanode启动不了
  4. 《企业迁云实战》——2.4 云端实践
  5. 1775. [国家集训队2010]小Z的袜子
  6. MongoDB 的分片技术
  7. 第19章 可空值类型
  8. 【NIO】dawn在buffer用法
  9. meta标签的另一个用法
  10. 虚拟系统管理VSM提高服务器整合率