Java Exception异常全方面分析

 更新时间:2022年03月23日 10:01:12   作者:来自爪哇的bean  
异常就是不正常,比如当我们身体出现了异常我们会根据身体情况选择喝开水、吃药、看病、等 异常处理方法。 java异常处理机制是我们java语言使用异常处理机制为程序提供了错误处理的能力,程序出现的错误,程序可以安全的退出,以保证程序正常的运行等

如下实例:

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

这段代码中“除0”的逻辑在C语言中就只是报个警告,但是Java是比较安全的语言,在编译运行的时候会直接抛出异常

那么到底什么是异常?

一、什么是异常?

异常指的是在程序运行过程中发生的异常事件,通常是由外部问题(如硬件错误、输入错误)所导致的。在Java等面向对象的编程语言中异常属于对象.

异常本身是一个对象,产生异常就是产生了一个异常对象

Java的异常体系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oL91wEfr-1645859727173)(C:\Users\LY\AppData\Roaming\Typora\typora-user-images\image-20220110210046681.jpg)]

我们都知道Java中所有类都是继承自Object的,Throwable这个类也是如此,如下Java官方文档

我们可以看到

继承于throwable类的有两个,一个是Error(错误),一个是Exception(异常),throwable是Java中所有错误和异常的父类

而异常又分为受查异常和非受查异常(我们之前碰到过的除0发生的异常就是非受查异常)

非受查异常:Java语言规范将派生于 Error 类或 RuntimeException 类的所有异常称为非受查异常(因为程序的代码Bug导致的问题,空指针异常,数组下标越界异常)

受查异常:所有的其他异常称为 受查异常(程序编译时抛出的异常),必须处理,否则代码编译不能通过(一些可以经过重试或者程序自动修复可以解决的问题)

错误:因为设备或其他硬性环境导致的,程序根本无法修复的问题

如何排查异常

如下代码:

在文章开头写的一个"除0"代码的运行结果:

这里面java.lang.ArithmeticException是异常的种类,by zero是异常的具体信息

常见的异常种类有:

NullPointerException:空指针异常

ArithmeticException:算术异常

ArrayIndexOutOfBoundsException:数组下标越界异常

PS:异常的种类有很多,不同的异常具有不同的含义,也有不同的处理方式

有的时候异常信息会有很多行,这些异常信息被称为异常信息栈/异常跟踪栈,那么我们如何在这些异常信息中找到引发异常的第一现场呢?

直接点击最上面第一条异常信息的蓝色部分,光标就会自动跳转到引发异常的地方,从而进行相应的修改

二、 处理异常

Java当中异常的核心思想其实就是让我们先操作,在操作过程中遇到问题再处理

try…catch基本语法

try{
有可能出现异常的语句;
}[catch (异常类型 异常对象) {
捕捉try当中可能出现的异常;
可以写多个catch;
} ... ]
[finally {
异常的出口;
可以不写;
finally中的代码一定会被执行,用来做一些善后工作;
}]

  • try 代码块中放的是可能出现异常的代码.
  • catch 代码块中放的是出现异常后的处理行为
  • finally 代码块中的代码用于处理善后工作, 会在最后执行.
  • 其中 catch 和 finally 都可以根据情况选择加或者不加.

我们还是以"除0"问题为例

public static void main(String[] args) {
    int a = 10/0;
    System.out.println("666");
}

这个程序显然到了int a = 10/0;就会抛出异常,后面的666不会被打印出来

此处发生异常,程序会直接交给JVM处理异常,导致的结果是程序会立即停止,不再向下执行

那么我们如果想要让程序继续往下执行呢?

这个时候就要处理异常

public static void main(String[] args) {
    try {
        int a = 10 / 0;
    } catch (ArithmeticException e) {
        e.printStackTrace();
    }
     System.out.println("666");
}

在try中放入可能会引发异常的语句,在catch后面的圆括号内写入想要捕获异常的种类ArithmeticException,然后就可以对此异常做出处理,e.printStackTrace();打印异常追踪栈,最后再打印666

运行结果:

当程序抛出异常的时候,由catch块进行捕获,程序自己来处理异常,导致的结果就是程序会继续向下执行

注意:如果catch中要捕获的异常种类和实际发生异常的种类不一样的话,就还是交给JVM处理了,程序立即停止

如果我们用Exception来捕获异常呢?

如下代码

public static void main(String[] args) {
    try {
        int a = 10 / 0;
    }catch (Exception e) {
        System.out.println(999);
    }catch (ArithmeticException e) {
        System.out.println(888);
    }     // 直接捕获Exception的话,后面的这些catch就没啥用了,编译器就会报错
    System.out.println("666");
}   

所有异常继承于Exception,那么当出现异常的时候,Exception可以捕获所有的异常,这样只需要写一个捕获Exception的catch就行了,但是不建议这么写,这样得不到具体的异常种类

finally

无论catch有没有捕获到异常,finally块中的代码都会在最后被执行

public static void main(String[] args) {
    try {
        int a = 10 / 0;
        System.out.println("666");
    }catch (ArithmeticException e) {
        System.out.println("888");
    }finally {
        System.out.println("999");
    }
    System.out.println("777");
}

在方法中出现异常

如果本方法中没有合适的处理异常的方式,就会沿着调用栈向上传递

public class ExceptionLearning {
    public static void demo() {
        int a = 10/0;
    }
    public static void main(String[] args) {
        demo();
    }
}

运行结果:

在demo方法中执行时,抛出算术异常,因为demo方法是被main方法调用的,所以demo就会让main方法来处理异常,但是main方法中也没有处理异常,就会交给JVM来处理,程序就会异常终止

若对异常做出处理

public class ExceptionLearning {
    public static void demo() {
        int a = 10/0;
    }
    public static void main(String[] args) {
        try {
            demo();
        }catch (ArithmeticException e) {
            e.printStackTrace();
        }finally {
            System.out.println("继续向下执行");
        }
    }
}

在demo方法中执行时,抛出算术异常,因为demo方法是被main方法调用的,所以demo就会让main方法来处理异常,main方法中对异常做出处理,程序继续向下执行

异常处理流程

  • 程序先执行 try 中的代码,如果 try 中的代码出现异常, 就会结束 try 中的代码, 看和 catch 中的异常类型是否匹配.
  • 如果找到匹配的异常类型, 就会执行 catch 中的代码,如果没有找到匹配的异常类型, 就会将异常向上传递到上层调用者.
  • 无论是否找到匹配的异常类型, finally 中的代码都会被执行到(在该方法结束之前执行).
  • 如果上层调用者也没有处理异常, 就继续向上传递,一直到 main 方法也没有合适的代码处理异常, 就会交给 JVM 来进行处理, 此时程序就会异常终止

手动抛出异常

除了Java编译器来抛出异常以外,我们也可以自己针对一些情况来抛出异常

三、自定义异常

要知道,异常本身就是一个对象,它肯定是对应一个类的,那么我们也可以通过创建类的方式来自定义异常

源码剖析

我们这里以Arithmetic类为例,可以先看看它的源码

从源码中会发现Arithmetic这个类继承自RuntimeException类,并且有两个构造方法,一个有参,一个无参

自定义

我们也可以仿照Arithmetic来自定义,如下代码

class MyException extends RuntimeException{
    public MyException() {
        super();
    }
    public MyException(String str) {
        super(str);
    }
}
public class ExceptionLearning {
    public static void main(String[] args) throws MyException{   //在方法上加上异常说明, 相当于将处理动作交给上级调用者
        int b = 0;
        if (b == 0) {
            throw new MyException("b == 0");
        }
    }
}

运行结果

注意

当我们将MyException继承于RuntimeException的时候,这个异常就默认是非受查异常;继承于Exception的时候,这个异常就默认是受查异常

Java针对受查异常,强制要求: 一个方法如果抛出了受查异常,则必须通过throws声明异常;如果抛出了非受查异常,则必须声明

到此这篇关于Java Exception异常全方面分析的文章就介绍到这了,更多相关Java 异常内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringMVC的执行过程浅析

    SpringMVC的执行过程浅析

    这篇文章主要给大家介绍了关于SpringMVC的执行过程的相关资料,文中通过图文介绍的非常详细,对大家的学习或者使用SpringMVC具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-03-03
  • 基于JTable的列宽与内容自适应的实现方法

    基于JTable的列宽与内容自适应的实现方法

    本篇文章是对JTable的列宽与内容自适应的实现方法进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • SpringBoot 启动方法run()源码解析

    SpringBoot 启动方法run()源码解析

    这篇文章主要介绍了SpringBoot 启动方法run()源码赏析,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • 使用@ConfigurationProperties注解获取为null的解决方法

    使用@ConfigurationProperties注解获取为null的解决方法

    在SpringBoot中,当想需要获取到配置文件数据时,除了可以用 Spring 自带的@Value注解外,SpringBoot还提供了一种更加方便的方式:@ConfigurationProperties,但我们在通过通过get方法去取值一直为null,本文介绍了使用@ConfigurationProperties注解获取为null的解决方法
    2024-09-09
  • Java由浅入深通关抽象类与接口下

    Java由浅入深通关抽象类与接口下

    在类中没有包含足够的信息来描绘一个具体的对象,这样的类称为抽象类,接口是Java中最重要的概念之一,它可以被理解为一种特殊的类,不同的是接口的成员没有执行体,是由全局常量和公共的抽象方法所组成,本文给大家介绍Java抽象类和接口,感兴趣的朋友一起看看吧
    2022-04-04
  • springmvc和js前端的数据传递和接收方式(两种)

    springmvc和js前端的数据传递和接收方式(两种)

    本文介绍了springmvc和js前端的数据传递和接收方式(两种),详细的介绍了两种方式,一种是json格式传递,另一种是Map传递,具有一定的参考价值,有兴趣的可以了解一下
    2017-12-12
  • java与c#的语法区别详细介绍

    java与c#的语法区别详细介绍

    由C#转入Java一段时间了,总结下个人认为的Java同C#语法之间的不同之处,有不同意见之处还望各位海涵,刚学Java时觉得语法同C#大致是相同的(应该说C#同Java大致相同
    2012-11-11
  • 关于SpringMVC请求域对象的数据共享问题

    关于SpringMVC请求域对象的数据共享问题

    这篇文章主要介绍了SpringMVC请求域对象的数据共享问题,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-02-02
  • Spring容器初始化及问题解决方案

    Spring容器初始化及问题解决方案

    这篇文章主要介绍了Spring容器初始化及问题解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-06-06
  • 深入探究如何使用Java编写MapReduce程序

    深入探究如何使用Java编写MapReduce程序

    MapReduce是一种用于处理大规模数据集的并行编程模型,其特点高效性和可扩展性,在本文中,我们将深入了解MapReduce,并使用Java编写一个简单的MapReduce程序,需要的朋友可以参考下
    2023-05-05

最新评论