• Java 异常


    1. 异常

    1.1 异常概念

    概念:指的是程序在执行过程中,出现的非正常的情况,最终导致JVM的非正常停止。

    在Java的面向对象的编程语言中,异常本身就是一个类,产生异常就是创建异常对象并抛出一个异常对象。Java处理异常的方式是中断处理。

    方法调用流程:

    Java虚拟机用方法调用栈(method invocation stack)来跟踪每个线程中一系列的方法调用过程。该堆栈保存了每个调用方法的本地信息(比如方法的局部变量)。每个线程都有一个独立的方法调用栈。对于Java应用程序的主线程,堆栈底部是程序的入口方法main()。当一个新方法被调用时,Java虚拟机把描述该方法的栈结构置入栈顶,位于栈顶的方法为正在执行的方法。

    当一个方法正常执行完毕,Java虚拟机会从调用栈中弹出该方法的栈结构,然后继续处理前一个方法。如果在执行方法的过程中抛出异常,则Java虚拟机必须找到能捕获该异常的catch代码块。它首先查看当前方法是否存在这样的catch代码块,如果存在,那么就执行该catch代码块;否则,Java虚拟机会从调用栈中弹出该方法的栈结构,继续到前一个方法中查找合适的catch代码块。在回溯过程中,如果Java虚拟机在某个方法中找到了处理该异常的代码块,则该方法的栈结构将成为栈顶元素,程序流程将转到该方法的异常处理代码部分继续执行。当Java虚拟机追溯到调用栈的底部的方法时,如果仍然没有找到处理该异常的代码块,按以下步骤处理。

    (1)调用异常对象的printStackTrace()方法,打印来自方法调用栈的异常信息。

    (2)如果该线程不是主线程,那么终止这个线程,其他线程继续正常运行。如果该线程是主线程(即方法调用栈的底部为main()方法),那么整个应用程序被终止。

    异常处理机制的优点

    在一些传统的编程语言,如C语言中,并没有专门处理异常的机制,程序员通常用方法的特定返回值来表示异常情况,并且程序的正常流程和异常流程都采用同样的流程控制语句。

    Java语言按照面向对象的思想来处理异常,使得程序具有更好的可维护性。Java异常处理机制具有一下优点:

    (1)把各种不同类型的异常情况进行分类,用Java类来表示异常情况,这种类被称为异常类。把异常情况表示成异常类,可以充分发挥类的可扩展和可重用的优势。

    (2)异常流程的代码和正常流程的代码分离,提高了程序的可读性,简化了程序的结构。

    (3)可以灵活的处理异常,如果当前方法有能力处理异常,就捕获并处理它,否则只需要抛出异常,由方法调用者来处理它。

    1.2 异常体系

    异常的根类:java.lang.Throwable,其中的两个子类:java.lang.Error 与 java.lang.Exception。


    (1)Throwable体系:

    • Error:无法通过处理的错误,只能事先避免。
    • Exception:表示异常,产生的异常程序员可以通过代码纠正,使程序继续运行,是必须要处理的。

    (2)Throwable中常用方法:

    • public void printStackTrace() : 打印异常详细信息(包含了异常类型,异常原因,还包括异常出现的位置)。
    • public String getMessage(): 获取发生异常的原因(提示给用户的时候,就提示错误原因)。
    • public String toString(): 获取异常的类型和异常描述信息(不常用)。

    1.3 异常分类

    (1)受检异常:
    checked exception。是程序执行期间发生的严重事件的后果。

    例如,如果程序想从磁盘读入数据,而系统找不到含有数据的文件,将会发生受检异常。

    受检异常的所有类都是类 Exception 的子类。

    Java 类库中的下列类表示受检异常:ClassNotFoundException、FileNotFoundException、IOException、NoSuchMethodException 及 WriteAbortedException。

    (2)运行时异常:
    runtime异常。通常是程序中逻辑错误的结果。

    运行时异常的所有类都是类 RuntimeException 的子类,它是 Exception 的后代。

    Java 类库中的下列类表示运行时异常:ArithmeticException、ArrayIndexOutOfBoundsException、ClassCastException等。

    (3)错误:
    错误(error)是标准类 Error 或其后代类的一个对象,这样的类都成为错误类(errorclass)。

    Error 是 Throwable 的后代。

    一般的,错误是指发生了不正确的情况,如内存溢出。

    2. 异常处理

    2.1 try-catch 块

    因为有输入操作而可能要处理 IOException 异常的代码段有如下形式:

    try
    {
        //<其他代码>
        anObject.readString(···); //可能抛出一个 IOException
        //<更多其他的代码>
    }
    catch (IOException e)
    {
        //< 响应异常代码,可能含有下面这行:>
        System.out.println(e.getMessage());
    }
    

    如果没有发生异常,则 try 块内的语句全部执行,然后执行 catch 块后的语句。如果在 try 块内发生了 IOException,则执行立即转到 catch 块。此时已经捕获了异常。

    作为一个对象,每个异常都有存取方法 getMessage(),它返回抛出异常时创建的描述字符串。

    在一个 try 块语句中,可能会抛出不同类型异常中的任意一个。在这样的 try 块后的 catch 块需要能捕获多个类的异常。为此可以在 try 块后写多个 catch 块。所以 catch 块出现的次序很重要。程序的执行流程进入到其参数与异常的类型相匹配的第一个 catch 块————按照出现的次序。

    例如,下列 catch 块的次序不好,因为 FileNotFoundException 的 catch 块永远不会执行:

    catch (IOException e)
    {
        ···
    }
    catch (FileNotFoundException e)
    {
        ···
    }
    

    按照这个次序,任何 I/O异常 都将被第一个 catch 块所捕获。因为 FileNotFoundException 派生于 IOException。

    2.2 finally 语句

    不论是否捕获到异常,总要执行 finally 后面的语句。一般地,为了统一处理程序出口,可将需公共处理的内容放到 finally 后的代码段中。

    示例:

    try {
        startFaucet();
        waterlawn();
    } finally {
        stopFaucet();
    }
    

    stopFaucet() 方法总被执行。try 后花括号中的代码成为保护代码。如果在保护代码内执行了 System.exit() 方法,将不执行 finally 后面的语句。

    2.3 公共异常

    (1)ArithmeticException
    整数除法中,如果除数为 0 ,则发生该类异常,例如:

    int i = 12 /0; 
    

    (2)NullPointerException
    如果一个对象还没有实例化,那么访问该对象或调用它的方法将导致 NullPointerException 异常。例如:

    image im [] = new image [4];
    System.out.println(im[0].toString());
    

    第一行创建了有 4 个元素的数组 im,每个元素都是 image 类型,系统为其进行初始化每个元素中的值为 null,表明它还没有指向任何实例。第二行要访问 im[0],由于访问的是还没有进行实例化的空引用,因此导致 NullPointerException 异常。

    (3)NegativeArraySizeException
    按常规,数组的元素个数应该是一个大于等于 0 的整数。创建数组时,如果元素个数是个负数,则会引发 NegativeArraySizeException 异常。

    (4)ArrayIndexOutOfBoundsException
    Java 把数组看作是对象,并用 length 变量记录数组的大小。访问数组元素时,运行时环境根据 length 值检查下表的大小。如果数组下标越界,则将导致 ArrayIndexOutOfBoundsException 异常。

    (5)SecurityException
    该类异常一般在浏览器内抛出。若 Applet 试图进行下述操作,则由 SecurityManager 类抛出此异常:

    • 打开本地文件。
    • 打开一个套接口,而不是返回到提供 Applet 的主机。
    • 在运行时环境中运行另一个程序。

    (6)ArrayStoreException
    程序试图存取数组中错误的数据类型。

    (7)FileNotFoundException
    试图存取一个并不存在的文件。

    (8)IOException
    该异常是指通常的 I/O 错误。

    3. 抛出异常

    当程序员不在当前方法内处理异常,而是把异常抛出到调用方法中。在不能使用合理的方式解决不正常或意外事件的情形下,才抛出异常。

    方法内执行 throw 语句时,需要创建一个对象,才会抛出一个异常。一般的形式是:

    throw new IOException();
    

    在说明方法时,具体格式如下:

    <访问权限修饰符><返回值类型><方法名> (参数列表) throws 异常列表
    

    紧接在关键字 throws 后面的是该方法内可能发生且不进行处理的所有异常列表。各异常之间以逗号分隔。

    如果方法内含有一个抛出异常的 throw 语句,则在方法头需要添加一个 throws 子句,而不是在方法体内捕获异常。一般地,抛出异常及捕获异常应该在不同的方法内。在方法头中用 Java 保留字 throws 声明这个方法可能抛出的异常。在方法体中用 throw 抛出一个异常。

  • 相关阅读:
    1203 有穷自动机
    [转]HTTP协议详解
    JavaScript中的正则表达式
    [译]JavaScript insertAdjacentHTML
    [译]Autoprefixer:用最可行的方式处理浏览器前缀的CSS后处理器
    [译]JavaScript 错误和处理
    [译]CSS content
    [译]当你在浏览器输入url后发生了什么
    display的小故事
    移动web屏幕适配方案
  • 原文地址:https://www.cnblogs.com/john1015/p/13883464.html
Copyright © 2020-2023  润新知