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日

相关推荐

  • Java自学之String类

    在实际项目开发中,String是一个必须使用的程序类,可以说是项目的核心组成类。在Java程序里所有的字符串都要求使用【’‘】进行定义,同时也可以利用【+】实现字符串的连接处理。 …

    2020年11月30日
    1.4K
  • Spring Boot的常用注解

    未来的框架趋势是“约定大于配置”,代码的封装会更加严密。开发人员会将更多的精力放在代码的整体优化和业务逻辑上,所以注解式编程会被更加广泛地使用。那么什么是注解?Spring Boo…

    2024年8月29日
    415
  • JAVA学习路线之夯实基础

    第一章 开发环境 JDK(Java SE Development Kit),Java标准版开发包,提供编译、运行Java程序所需的各种工具和资源,包括Java编译器、Java运行环…

    2020年1月14日
    1.7K
  • Java自学之泛型

    在Java语言中,为了方便接收参数类型的统一,提供了核心类Object,利用此类对象可以接收所有类型的数据(包括基本数据类型和引用数据类型)。但是由于其所描述的数据范围过大,所以在…

    2020年12月8日
    1.3K
  • Java自学之反射机制

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

    2020年12月24日
    1.2K
  • STS插件mybatis-generator安装及使用

    断断续续学习Java也有好长时间了,没有师傅带,没有项目练手,学习超级慢,也很烦。视频、书籍翻看了一大推,还是没有目标。 相信滴水成海,外加条条大路通罗马,只要坚持,自己终能达成目…

    2019年12月27日
    2.3K
  • Java自学之I/O编程

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

    2020年12月21日
    1.3K
  • JAVA学习之多线程知识点整理

    1、什么是进程?什么是线程? 进程是一个应用程序。线程是一个进程中的执行场景或者执行单元。一个进程可以启动多个线程。进程之间内存独立不共享。同一个进程中的线程之间,堆内存和方法区内…

    2020年6月19日
    1.3K
  • spring boot练习篇之用户登录系统【接入数据库】

    抛弃JSP,只做纯粹的前后端分离项目。 写在前面 学习基础知识是枯燥无味的,之所以会这样,多数是因为心不静,对于如何运用它,感到茫然。所以建议大家在学习Java基础知识的时候,一定…

    2021年5月28日
    1.3K
  • spring boot练习篇之用户登录系统【接口篇】

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

    2021年5月25日
    1.7K

发表回复

登录后才能评论