Java Exception异常全方面分析

目录
  • 一、什么是异常?
    • Java的异常体系
    • 如何排查异常
  • 二、 处理异常
    • try…catch基本语法
    • 这个时候就要处理异常
    • 如果我们用Exception来捕获异常呢?
    • finally
    • 在方法中出现异常
    • 异常处理流程
    • 手动抛出异常
  • 三、自定义异常
    • 源码剖析
    • 自定义
    • 注意

如下实例:

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

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

那么到底什么是异常?

一、什么是异常?

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

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

Java的异常体系

我们都知道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 异常内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java java.lang.InstantiationException异常案例详解

      java.lang.InstantiationException 是指不能实例化某个对象,一般在我们使用java反射机制去创建某个对象的时候实例化到了一个抽象类或者接口(java中抽象类和接口是不能被实例化),而今天我遇到的则是我在使用反射机制实例化某个持久类的时候爆出这个异常,后来发现是因为iBATIS在对象建立中,会使用不带参数的构造函数来建立对象,而自己的持久化类中含有带参数的构造方法,将默认无参构造方法覆盖,导致在实例化过程出现异常.所以在定义一个无参构造方法可解决. 异常 持久类没

  • java.lang.ArrayStoreException异常的解决方案

    java.lang.ArrayStoreException异常 异常提示 java.lang.ArrayStoreException: java.lang.Boolean at java.util.stream.Nodes$FixedNodeBuilder.accept(Nodes.java:1222) at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) at java.util.Spliter

  • Java中java.lang.ClassCastException异常原因及解决方法

    通常我们在 OOP 设计中都会使用到继承. ​​但是在继承对象之间的强制转换可能会遇到​​java.lang.ClassCastException​​异常的错误. 错误的日志如下: 19:58:25.010 [http-nio-8080-exec-5] ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw

  • 解决Java的InputMismatchException异常

    一.写在前面 InputMismatchException异常是输入不匹配异常,即输入的值数据类型与设置的值数据类型不能匹配. 二.异常的出现原因 在使用Scanner进行输入时,报出InputMismatchException异常,其代码如下: public static void main(String[] args) { Scanner sc=new Scanner(System.in); System.out.println("请输入一个数字:"); int x=sc.next

  • Java异常(Exception)处理以及常见异常总结

    目录 前言 异常简介 异常类型 总结 前言 很多事件并非总是按照人们自己设计意愿顺利发展的,经常出现这样那样的异常情况.例如: 你计划周末郊游,计划从家里出发→到达目的→游泳→烧烤→回家.但天有不测风云,当你准备烧烤时候突然天降大雨,只能终止郊游提前回家."天降大雨"是一种异常情况,你的计划应该考虑到这样的情况,并且应该有处理这种异常的预案. 计算机程序的编写也需要考虑处理这些异常情况.异常(exception)是在运行程序时产生的一种异常情况,已经成为了衡量一门语言是否成熟的标准之一

  • Java ClassCastException异常解决方案

    ClassCastException是JVM在检测到两个类型间转换不兼容时引发的运行时异常.此类错误通常会终止用户请求.在执行任何子系统的应用程序代码时都有可能发生ClassCastException异常.通过转换,可以指示Java编译器将给定类型的变量作为另一种变量来处理.对基础类型和用户定义类型都可以转换.Java语言规范定义了允许的转换,其中大多数可在编译时进行验证.不过,某些转换还需要运行时验证.如果在此运行时验证过程中检测到不兼容,JVM就会引发ClassCastException异常

  • Java Exception异常全方面分析

    目录 一.什么是异常? Java的异常体系 如何排查异常 二. 处理异常 try…catch基本语法 这个时候就要处理异常 如果我们用Exception来捕获异常呢? finally 在方法中出现异常 异常处理流程 手动抛出异常 三.自定义异常 源码剖析 自定义 注意 如下实例: public class Demo { public static void main(String[] args) { int num = 2/0; } } 这段代码中“除0”的逻辑在C语言中就只是报个警告,但是Ja

  • 详解Java的Exception异常机制

    一.前言 在Java中,我们在执行代码的过程中难免会遇到错误与Exception异常,可是我们一直都是锤头Coding而忽略了学习Exception这个东西!我们只是知道在发生Exception的地方让代码自动生成throw exception或者是使用try-catch括起来处理,那你了解Java的Exception吗?今天就让我们把一起来看看Java的Exception吧! 在Java中,我们的代码再出现错误的时候无非是两种情况:一是Error,一是异常Exception.如果是Error,

  • Java 常见异常(Runtime Exception )详细介绍并总结

    本文重在Java中异常机制的一些概念.写本文的目的在于方便我很长时间后若是忘了这些东西可以通过这篇文章迅速回忆起来. 1. 异常机制 1.1 异常机制是指当程序出现错误后,程序如何处理.具体来说,异常机制提供了程序退出的安全通道.当出现错误后,程序执行的流程发生改变,程序的控制权转移到异常处理器. 1.2 传统的处理异常的办法是,函数返回一个特殊的结果来表示出现异常(通常这个特殊结果是大家约定俗称的),调用该函数的程序负责检查并分析函数返回的结果.这样做有如下的弊端:例如函数返回-1代表出现异常

  • java的异常与处理机制分析【附面试题】

    本文实例讲述了java的异常与处理机制.分享给大家供大家参考,具体如下: java的异常机制 Throwable类 Throwable类是Java异常类型的顶层父类,一个对象只有是 Throwable 类的(直接或者间接)实例,他才是一个异常对象,才能被异常处理机制识别.JDK中内建了一些常用的异常类,我们也可以自定义异常. Throwable又派生出Error类和Exception类. 错误:Error类以及他的子类的实例,代表了JVM本身的错误.错误不能被程序员通过代码处理,Error很少出

  • Java 异步线程监听与结果回调及异常捕获总结分析

    前言 工作中是否遇到这样的场景? 1.需要异步线程执行,而且需要获取到线程执行返回的结果. 2.如果执行过程异常,可以按照自定义方式消费异常信息. 如果只是单纯的使用Callable可以实现,本文提供更加优雅的工具类. Maven依赖 <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.7.15</ver

  • Java中异常打印输出的常见方法总结

    前言 Java异常是在Java应用中的警报器,在出现异常的情况下,可以帮助我们程序猿们快速定位问题的类型以及位置.但是一般在我们的项目中,由于经验阅历等多方面的原因,依然有若干的童鞋在代码中没有正确的使用异常打印方法,导致在项目的后台日志中,没有收到日志或者日志信息不完整等情况的发生,这些都给项目埋下了若干隐患.本文将深入分析在异常日志打印过程中的若干情况,并给出若干的使用建议. 1. Java异常Exception的结构分析 我们通常所说的Exception主要是继承于Throwable而来,

  • 详解java JDK 动态代理类分析(java.lang.reflect.Proxy)

    详解java JDK 动态代理类分析(java.lang.reflect.Proxy) /** * JDK 动态代理类分析(java.lang.reflect.Proxy使用) * * @author 张明学 * */ public class ProxyStudy { @SuppressWarnings("unchecked") public static void main(String[] args) throws Exception { // 动态代理类:通用指定类加载器,和接

  • Java常见异常及处理方式总结

    一.概述 异常指不期而至的各种状况,它在程序运行的过程中发生.作为开发者,我们都希望自己写的代码 永远都不会出现 bug,然而现实告诉我们并没有这样的情景.如果用户在程序的使用过程中因为一些原因造成他的数据丢失,这个用户就可能不会再使用该程序了.所以,对于程序的错误以及外部环境能够对用户造成的影响,我们应当及时报告并且以适当的方式来处理这个错误. 之所以要处理异常,也是为了增强程序的鲁棒性. 异常都是从 Throwable 类派生出来的,而 Throwable 类是直接从 Object 类继承而

  • Java struts2请求源码分析案例详解

    Struts2是Struts社区和WebWork社区的共同成果,我们甚至可以说,Struts2是WebWork的升级版,他采用的正是WebWork的核心,所以,Struts2并不是一个不成熟的产品,相反,构建在WebWork基础之上的Struts2是一个运行稳定.性能优异.设计成熟的WEB框架. 我这里的struts2源码是从官网下载的一个最新的struts-2.3.15.1-src.zip,将其解压即可.里面的目录页文件非常的多,我们只需要定位到struts-2.3.15.1\src\core

  • Java RabbitMQ高级特性详细分析

    目录 消息的可靠投递 确认模式 退回模式 Consumer Ack 消费端限流 TTL(Time To Live) 设置某个队列为过期队列 设置单独某个消息过期 死信队列 延迟队列 消息的可靠投递 在使用 RabbitMQ 的时候,作为消息发送方希望杜绝任何消息丢失或者投递失败场景.RabbitMQ 为我们提供了两种方式用来控制消息的投递可靠性模式. confirm 确认模式 return 退回模式 rabbitmq整个消息投递的路径为: producer—>rabbitmq broker—>

随机推荐