Java自学之异常的捕获与处理

在程序开发中,程序的编译与运行是两个不同的阶段,编译主要针对的是语法检测,而在程序运行时却有可能出现各种各样的错误导致程序中断执行,那么这些错误在Java中统一称为异常。

异常处理

在Java中,针对异常的处理提供3个核心关键字:try、catch、finally,利用这几个关键字就可以组成以下的异常处理格式。

try {
     // 有可能出现异常的语句
 }[ catch(异常类型 对象) {
     // 异常处理
 } catch(异常类型 对象) {
     // 异常处理
 } …] [finally {
     // 不管是否出现异常,都执行的统一代码
 }]

在格式种,已经明确表示,在try语句中捕获可能出现的异常代码。如果在try中产生了异常,则程序会自动跳转到catch语句中找到匹配的异常类型进行相应的处理。最后不管程序是否会产生异常,则肯定会执行到finally语句,finally语句就作为异常的统一出口,需要注意的是,finally块是可以省略的。

异常的基本处理流程如下图所示。

Java自学之异常的捕获与处理

在异常处理的格式中,catch与finally都是可选的,实际上并不表示这两个语句可以同时消失,对于异常格式的组合,往往有以下几种结构形式:try…catch、try…catch…finally、try…finally。

在进行异常捕获与处理时,每一个try语句后可以设置多个catch语句,用于进行各种不同类型的异常捕获。处理多个异常时,捕获范围小的异常要放在捕获范围大的异常处理之前处理。

在Java中的完整异常处理流程如下图。

Java自学之异常的捕获与处理

关于此流程图的说明如下。

  1. Java中可以处理的异常全部都是在程序运行中产生的异常,当程序运行到某行代码并且此代码执行出现异常时,会有JVM帮助用户去判断此异常的类型,并且自动进行指定类型的异常类对象实例化处理。
  2. 如果此时程序中并没有提供异常处理的支持,则采用JVM默认异常处理方式【图中红实线流程】,首先进行异常信息的打印;其次直接退出当前程序。
  3. 如果此时程序中存在异常处理,那么这个产生的异常类的实例化对象将会被try语句所捕获。
  4. try捕获到异常之后与其匹配的catch中的异常类型依次进行比对,如果此时与catch中的捕获异常类型相同,则认为应该使用此catch进行异常处理;如果不匹配则继续匹配后续的catch类型;如果没有任何的catch匹配成功,那么就表示该异常无法进行处理。
  5. 不管异常是否处理最终都要执行finally语句,但是当执行完成finally的程序代码之后会进一步判断当前的异常是否已经处理过了,如果处理过了,则继续向后执行其他代码;如果没有处理则交由JVM进行默认处理。

通过分析可以发现在整个异常处理流程中实际上操作的是一个异常类的实例化对象,这个异常类的实例化对象的类型就是异常处理的核心关键。

throws关键字

在程序执行的过程中往往会涉及不同类中方法的调用,而为了方便调用者进行异常的处理,往往会在这些方法声明时对可能产生的异常进行标记,此时就需要通过throws关键字来实现。

package cn.uihtml.demo;
 class MyMath {
     /**
     * 定义数字除法运算,执行时可能会产生异常
     * @param x 除数
     * @param y 被除数
     * @return 除法运算结果
     * @throws Exception 计算过程中产生的异常,可以是具体异常类型,也可以简化使用Exception
     */
     public static int div(int x,int y) throws Exception {
         return x / y;
     }
 }
package cn.uihtml.demo;
 class JavaDemo {
     public static void main(String[] args) {
         try {
             System.out.println(MyMath.div(10,0))
         } catch {
             e.printStackTrace();
         }
     }
 }

throw关键字

在默认情况下,所有的异常类的实例化对象都会由JVM默认实例化并且自动抛出。为了方便用户手动进行异常的抛出,JVM提供了有一个throw关键字。

package cn.uihtml.demo;
 class JavaDemo {
     public static void main(String[] args) {
         try {
             throw new Exception('手动抛出异常类实例化对象');
         } catch (Exception e) {
             e.printStackTrace();
         }
     }
 }

throw 与 throws关键字的区别

【throw】是在代码块中使用,主要是手动进行异常对象的抛出。
【throws】是在方法定义中使用,表示将此方法中可能产生的异常明确告诉给调用处,由调用出进行处理。

异常处理模型

实现合理的异常处理

package cn.uihtml.demo;
 class MyMath {
     public static int div(int x, int y) throws Exception {
         int temp = 0;
         System.out.println('计算开始……');
         try {
             temp = x / y;
         } catch (Exception e) {
             throw e;
         } finally {
             System.out.println('计算结束……');
         }
         return temp;
     }
 }
package cn.uihtml.demo;
 class JavaDemo {
     public static void main(String[] args) {
         try {
             System.out.println(MyMath.div(10,0));
         } catch (Exception e) {
             e.printStackTrace();
         }
     }
 }

本程序利用几个异常处理关键字实现了一个标准的异常处理流程,在div()方法中不管是否产生异常都会按照既定的结构执行,并且会产生的异常交由调用处来进行处理。

使用简化异常模型

package cn.uihtml.demo;
 class MyMath {
     public static int div(int x, int y) throws Exception {
         int temp = 0;
         System.out.println('计算开始……');
         try {
             temp = x / y;
         } finally {
             System.out.println('计算结束……');
         }
         return temp;
     }
 }

本程序取消了catch语句,这样一旦产生异常,在执行完finally语句之后,由于本方法没有任何的异常处理语句,所以会将异常直接通过方法声明的throws交给调用处进行处理。

RuntimeException

在Java里为了方便用户代码的编写,专门提供了一种RuntimeException类,这种异常类的最大特征在于:程序在编译的时候不会强制性地要求用户处理异常,用户可以根据自己需要进行选择性处理。但是如果没有处理异常又发生了异常,将交给JVM默认处理。也就是说,RuntimeException的子异常类可以由用户根据需要选择性进行处理。

public static int parseInt(String s) throws NumberFormatException

parseInt()方法抛出一个NumerFormatException,而这个异常类就属于RuntimeException子类。

自定义异常类

Java本身已经提供了大量的异常类,但是这些异常类在实际的工作中往往并不够使用,此时用户可以选择自定义一个异常类进行处理。

实现自定义异常类

package cn.uihtml.demo;
 class BombException extends Exception {
     public BombException(String msg) {
         // 调用父类构造方法
         super(msg);
     }
 }
package cn.uihtml.demo;
 class Food {
     public static void eat(int num) throws BombException {
         if (num > 999) {
             throw new BombException('东西太多,承受不了……');
         } else {
             System.out.println('在能力承受范围之内,可以消化掉……')
         }
     }
 }
package cn.uihtml.demo;
 class JavaDemo {
     public static void main(String[] args) {
         try {
             Food.eat(1000);
         } catch (BombException e) {
             e.printStackTrace();
         }
     }
 }

assert关键字

assert关键字主要功能是进行断言,断言是指程序执行到某行之后,其结果一定是预期的结果。

package cn.uihtml.demo;
 class JavaDemo {
     public static void main(String[] args) {
         int x = 10;
         // 中间可能会经过许多程序语句,导致变量x的内容发生改变
         assert x = 100 : 'x的内容不是100';
         System.out.println(x);
     }
 }

Java中默认是不开启断言运行的,可以使用以下语句开启断言运行。

java -ea cn.uihtml.demo.JavaDemo

原创文章,作者:ZERO,如若转载,请注明出处:https://www.edu24.cn/course/java/java-exception.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
ZEROZERO
上一篇 2020年12月10日
下一篇 2020年12月14日

相关推荐

  • spring4.x学习之创建工程

    断断续续学习Java有两三个月了,目前还是处于入门阶段。关于java及spring那些的设计理念方面的理论知识,不花费大量精力及时间是看不懂的(至少对于我这么一个前端转后端的初学者…

    2019年3月19日
    1.8K
  • Java自学之多线程编程

    多线程编程是Java语言最为重要的特性之一。利用多线程技术可以提升单位时间内的程序处理性能,也是现代程序开发中高并发的主要设计模式。 进程与线程 进程是一个应用程序。线程是一个进程…

    2020年12月16日
    1.5K
  • Java自学之抽象类与接口

    面向对象程序设计中,类继承的主要作用的扩充已有类的功能。子类可以根据自己的需要选择是否要覆写父类中的方法,所以一个设计完善的父类是无法对子类做出任何强制性的覆写约定。为了解决这样的…

    2020年12月7日
    1.2K
  • Java自学之I/O编程

    I/O(Input/Output,输入/输出)可以实现数据的读取与写入操作,Java针对I/O操作的实现提供了java.io工具包,此包的核心组成由File类、InputStrea…

    2020年12月21日
    1.2K
  • MyBatis之MyBatis-Generator标签配置及意义

    DTD 标签 <generatorConfiguration/>: 根标签,所有的配置都必须在该标签内配置;没有属性 <properties/>: 主要引用外部的pro…

    2019年12月27日
    1.8K
  • spring4.x学习之用户登录与注册

    在之前的文章中我已经把后端工程项目创建好了,接下来就是编写项目了。 首先,我先创建一个数据库。数据库使用的是MySQL,数据库管理工具用的是Navicat。 打开数据库管理工具Na…

    2019年3月21日
    2.0K
  • servlet学习之获取表单数据(IDEA2020.2篇)

    首先,创建一个servlet工程。 如果你不会用IDEA2020.2创建servlet工程,请打开下面链接浏览网站博文。 https://www.edu24.cn/course/j…

    2020年9月8日
    1.4K
  • Java自学之反射机制

    重用性是面向对象设计的核心原则。为了进一步提升代码的重用性,Java提供了反射机制。反射技术首先考虑的是“反”与“正”的操作,所谓的“正”操作,是指当开发者使用一个类的时候,一定要…

    2020年12月24日
    1.2K
  • JAVA基础知识整理

    终于下定决心2020年转JAVA开发,自学之路坎坷曲折。俗话说的话,好记性不如烂笔头。如果有小伙伴们也像我一样在JAVA自学之路上徘徊,那就关注一下我的博客网站。我会不定期更新一下…

    2020年1月11日
    1.7K
  • spring boot练习篇之用户登录系统【接口篇】

    写在前面 抛弃JSP,只做纯粹的前后端分离项目。 作为一个资深前端工作者,想要转JavaWeb开发,无论是书籍,还是网上视频、资料,竟然没有一篇能清楚明白地讲解怎样搭建一个前后端分…

    2021年5月25日
    1.6K

发表回复

登录后才能评论