zoukankan      html  css  js  c++  java
  • 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 抛出一个异常。

  • 相关阅读:
    poj 1579(动态规划初探之记忆化搜索)
    hdu 1133(卡特兰数变形)
    CodeForces 625A Guest From the Past
    CodeForces 625D Finals in arithmetic
    CDOJ 1268 Open the lightings
    HDU 4008 Parent and son
    HDU 4044 GeoDefense
    HDU 4169 UVALive 5741 Wealthy Family
    HDU 3452 Bonsai
    HDU 3586 Information Disturbing
  • 原文地址:https://www.cnblogs.com/john1015/p/13883464.html
Copyright © 2011-2022 走看看