浅谈异常

 

1.异常的概述

什么是异常

是一个在程序执行期间发生的事件,它中断正在执行程序的正常指令流。为了能够及时有效地处理程序中的运行错误,必须使用异常类

异常类

  • 在Java中将异常的信息封装成一个类
  • 当程序出现异常时,就会创建异常类对象并抛出异常相关的信息(如异常出现的位置,原因)

常见的异常

  • 数组越界异常:ArrayIndexOutOfBoundsException
  • 空指针异常:NullPointerException
  • 算数异常以0作除数:ArithmeticException: / by zero

2.异常的继承体系和错误的区别

异常的继承体系

在 Java 中所有异常类型都是内置类 java.lang.Throwable 类的子类,即 Throwable 位于异常类层次结构的顶层

Throwable类下有两个分支 Exception 和 Error   如下图所示

由图所知,Throwable 类是所有异常和错误的超类,下面有 Error 和 Exception 两个子类分别表示错误和异常。其中异常类 Exception 又分为运行时异常和非运行时异常,这两种异常有很大的区别,也称为不检查异常(Unchecked Exception)和检查异常(Checked Exception)

  • 运行时异常:都是 RuntimeException 类及其子类异常,如 NullPointerExceptionIndexOutOfBoundsException 等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般由程序逻辑错误引起,程序应该从逻辑角度尽可能避免这类异常的发生。
  • 非运行时异常:是指 RuntimeException 以外的异常,类型上都属于 Exception 类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如 IOExceptionClassNotFoundException 等以及用户自定义的 Exception 异常,

异常与错误的区别

异常

  • 指程序在编译期间,运行时期发生了某种异常,我们可以对异常进行处理
  • 如若不处理异常,程序将会结束
  • 举了例子
public static void main(String[] args) {
        int[] arr = {1,2,3};
        System.out.println(arr[3]);
        //该句运行时会发生数组越界异常ArraylndexOutOfBoundException
        //由于没有处理异常,导致程序无法继续进行,无法打印程序结束
        System.out.println("程序结束");
}

错误

  • 描述Java运行时内部出错或者资源耗尽错误(只能终止程序)

  • Error 错误的发生往往都是系统级别的问题,都是 JVM 所在系统发生的,并反馈给 JVM 

  • 无法针对处理,只能修改代码

  • 举了例子

public static void main(String[] args) {
        int array[] = new int[1024*1024*1024];
        //该句运行时JVM无法分配足够的空间,发生了内存溢出错误OutOfMemoryError
        //程序也会立即结束,不会打印程序结束
        System.out.println("程序结束");
}

3.异常对象的产生原因和处理方式

异常对象的产生原因

举个例子

class ArrayTools{
    //对给定的数组通过给定的角标获取元素。
    public static int getElement(int[] arr,int index)	{
        int element = arr[index];
        return element;
    }
}
public class Test {
    public static void main(String[] args) 	{
        int[] arr = {34,12,67};
        int num = ArrayTools.getElement(arr,4);//静态方法用类名调用,不依赖于对象
        System.out.println("num="+num);
        System.out.println("程序结束");
    }
}

原因分析

  • 由于没有找到索引 4,导致运行时发生了异常。这个异常JVM认识:ArrayIndexOutOfBoundsException 这个异常Java本身有描述:异常的名称、异常的内容、异常的产生位置
  • Java将这些信息直接封装到对象中,new ArrayIndexOutOfBoundsException(4)JVM将产生的异常抛给调用者main() 方法
  • main() 方法接收到了数组索引越界异常对象。由于main()方法并没有进行处理异常,main()方法就会继续把异常抛给调用者JVM
  • 当JVM收到异常后,将异常对象中的名称、异常内容、位置都显示在就控制台上。同时让程序立刻终止

异常的处理方式

JVM的默认处理方法

  • 把异常的名称,原因,位置等信息输出在控制台,同时立即结束程序
  • 一旦有异常出现,代码将不再往下继续进行

解决程序中异常的手动方式

  • 编写处理代码 try...catch...finally
  • 抛出 throws

4.方法内部抛出对象throw关键字

在java中,提供了一个throw关键字,它用来抛出一个指定的异常对象

什么时候使用throw关键字?

当调用方法使用接受到的参数时,首先需要先对参数数据进行合法的判断,数据若不合法,就应该告诉调用者,传递合法的数据进来。这时需要使用抛出异常的方式来告诉调用者。

使用throw关键字具体操作

  • 创建一个异常对象,封装一些提示信息(信息可以自己编写)
  • 通过关键字 throw 将这个异常对象告知给调用者。throw 异常对象
  • throw 用在方法内,用来抛出一个异常对象,将这个异常对象传递到调用者处,并且结束当前方法的执行

throw关键字使用格式

  • throw new 异常类名(参数)
  • eg:throw new NullPointerException("数组为null");
  • eg:throw new ArrayIndexOutOfBoundsException("数组越界");

5.方法声明异常关键字throws

声明

将可能出现的问题标识出来,报告给调用者。如果方法内部通过 throw 抛出了编译时异常,而没有捕获处理(稍后讲解该部分),那么必须通过 throws 进行声明,让调用者去处理

声明异常格式

修饰符 放回值类型 方法名(参数) throws 异常类名1,异常类名2...{  }

注意事项

若方法可能出现多种异常,那么可以在 throws 关键字后写多个异常类名,用逗号隔开

6.try...catch异常处理

捕获

Java中对异常有针对性的语句进行捕获,可以对出现的异常进行指定性的处理

捕获异常的格式

        try{
               //需要被检测的语句(可能出现异常的语句)
        }
        catch (异常类 变量) {
               //异常的处理方式
        }
        finally{
               //一定会被执行的语句
        }

格式说明

  • try:该代码块中可能会产生异常的语句
  • catch:用来对某种异常的捕获,实现对捕获到的异常进行处理
  • finally:这部分的代码是一定会被执行的。异常的出现会导致代码不再执行,而一些特定的代码无论异常是否产生,都需要执行
  • try...catch...  处理异常后,程序将可以继续进行 

多catch处理

一个 try 多个 catch 组合

对代码进行异常检测,并对检测的异常传递给catch处理。对每种异常信息进行不同的捕获处理

多catch处理的格式

注意:在捕获异常处理时,变量也是有作用域的,如可以定义多个异常变量名 e 

    void show() { //不用throws
        try{
            throw new Exception();//产生异常直接捕获处理
        }
        catch (XxxException e) {
            //处理方式
        }
        catch (YyyException e) {
            //处理方式
        }
        catch (ZzzException e) {
            //处理方式
        }
        finally{
            //处理方式
        }

多 catch 处理细节

  • 多个catch小括号中,写的是异常类的类名,有没有顺序的影响。
  • 平级异常:抛出的异常类之间,没有继承关系,没有顺序
  • 上下级关系的异常:越高级的父类,越写在下面

7.finally代码块

finally 代码块的特点

被 finally 控制的语句体一定会执行

finally的作用

finally无论程序是否有异常出现,程序必须执行释放资源,如:IO流操作和数据库操作中会见到

8.运行时期异常的特点

运行时期异常的概述

RuntimeException和他的所有子类异常都属于运行时期异常

NullPointerException,ArrayIndexOutOfBoundsException等都属于运行时期异常

运行时期异常的特点

  • 方法中抛出运行时期异常,方法定义中无需 throws 声明,调用者也无需处理此异常。
  • 运行时期异常一旦发生,需要程序人员修改源代码。

9.自定义异常

自定义异常的定义

阅读源码发现:每个异常中都调用了父类的构造方法,把异常描述信息传递给了父类,让父类帮我们进行异常信息的封装

格式

Class 异常名 extends Exception{ //或继承RuntimeException
    public 异常名(){
    }
    public 异常名(String s){ 
        super(s); 
    }
}

自定义异常的练习

  • ​​​​​​​在 Person 类的有参构造方法中,进行年龄的判断,年龄为负数或者大于200岁的,则抛出 NoAgeException异常,异常提示信息“年龄数值非法”
  • 在测试类中,调用有参的构造方法,完成Person类对象的创建,应对异常进行处理

关于构造方法抛出异常总结

构造函数到底抛出这个NoAgeException是继承Exception呢?还是继承RuntimeException呢?

  • 继承Exception,必须要 throws 声明,一声明就告知调用者进行捕获,一旦问题处理了调用者的程序会继续执行
  • 继承RuntimeExcpetion,不需要 throws 声明的,这时调用是不需要编写捕获代码的,因为调用根本就不知道有问题
  • 一旦发生NoAgeException,调用者程序会停掉,并有JVM将信息显示到屏幕,让调用者看到问题,修正代码。

​​​​​​​

发布了20 篇原创文章 · 获赞 9 · 访问量 900

猜你喜欢

转载自blog.csdn.net/weixin_44915811/article/details/104235216
今日推荐