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

Like (0)
Donate 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
ZEROZERO
Previous 2020年12月10日
Next 2020年12月14日

相关推荐

  • Java自学之抽象类与接口

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

    2020年12月7日
    1.1K
  • spring4.x学习之用户登录与注册

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

    2019年3月21日
    1.8K
  • Java自学之泛型

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

    2020年12月8日
    1.2K
  • 如何使用IDEA2020.2新建servlet工程

    最近自学java时,发现IDEA更新到2020.2版本时,在新建工程时,有了明显的改动。由于小编刚学到servlet,IDEA这一突然间的改动,导致小编不会新建servlet工程了…

    2020年8月17日
    5.5K
  • Spring Tools学习之JAVA开发环境搭建【windows 10】

    一直以来都想学习JAVA,但是苦于找不到门路,网上学习资料要不看不懂,要不需要金钱。 终于,迫于生活与年龄的压力,下定决心,学习JAVA。 写下此文档,记录一下自己学习JAVA之路…

    2018年12月6日
    2.7K
  • Java自学之类结构扩展

    面向对象中的核心组成是类与接口,在项目中会利用【包】进行一组相关类的管理,这样适合于程序代码的部分更新,也更加符合面向对象封装性的概念,同时合理地使用封装也可以方便地实现实例化对象…

    2020年12月10日
    1.2K
  • Java自学之内部类

    内部类是一种常见的嵌套结构,利用这样的结构使得内部类可以与外部类共存,并且方便地进行私有操作的访问。 内部类基本概念 内部类(内部定义普通类、抽象类、接口的统称)是指一种嵌套的结构…

    2020年12月14日
    1.3K
  • Spring Boot的常用注解

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

    2024年8月29日
    261
  • MyBatis之MyBatis-Generator标签配置及意义

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

    2019年12月27日
    1.7K
  • JavaWeb入门案例之用户注册

    前言 之前把Java的基础知识系统的过了一遍,目前总算可以看懂Java代码了,接下来就是要学习Java开发框架(主要是springMVC)。 下面用一个用户注册的小案例,来总结一下…

    2021年1月13日
    1.4K

发表回复

Please Login to Comment