Java异常处理机制

  异常允许我们强制停止程序运行,并告诉我们出现了什么问题,或者强制程序去处理问题,并返回到稳定状态。

Java提供一个Throwable类,该类是所有异常和错误类的超类。只有当对象是此类的实例时,才能通过Java虚拟机或者Java的throw语句抛出。throwable类及其子类的结构图:

一、异常类型

  Error:一般是指严重的系统错误,与虚拟机相关的问题,如系统崩溃,虚拟机出错,动态链接失败等,这一类的错误一般无法修复或不可能捕获,将导致应用程序中断。

  Exception:是指一些可以捕获且可能恢复的异常情况,如数组下标越界ArrayIndexOutOfBoundsException、数字被零除产生异常ArithmeticException、输入输出异常IOException等。

  可以知道Error属于JVM需要负担的责任,RuntimeException类是程序应该负担的责任,受检异常是具体应用负担的责任。作为程序员关心的就是Exception。

1、非受检异常

  是指编译器不要求强制处置的异常,一般是编程时的逻辑错误,是程序员应该避免的,RuntimeException类以及他的子类都是非受检异常的,具体如下:

  1)错误的类型转换:ClassCastException

  2)组下标越界:ArrayIndexOutOfBoundsException

  3)空指针访问异常:NullPointerException

  4)被零除产生异常:ArithmeticException

2、受检异常

  编译器要求必须处置的异常,及程序运行时由于外界因素造成的一般性异常,具体如下:

  1)没有找到具体指定名称的类异常:ClassNotFoundException

  2)访问不存在的文件异常:FileNotFoundException

  3)操作文件异常:IOException

  4)操作数据库时发生异常:SQLException

Java要求Java程序必须捕获或声明所有的受检异常,对于这类异常,如果程序不做处理,则将会带来意想不到的结果,而非受检异常可以不做任何处理。

二、捕获异常语句

  1、try……catch……finally……

    try选定要捕获异常的范围,在执行时,catch后面括号内的代码会产生异常对象并抛出,然后用catch块来处理异常。

    finally不管是否有异常发生都要执行的语句块,如数据库的关闭。要注意:如果try语句块中有一个明确的return语句,finally快也总是在return前执行。

 

  2、throws 和 throw

    throw:语句明确的抛出一个异常,必须是一个throwable 的类,或者new来创建一个实例:throw new XXException();

    执行throw语句后,运行流程将立即停止throw的下一条语句也将暂停执行。

    throws:如果一个方法a可以引发异常,而他本身并不对该异常进行处理,那么a方法必须将这个异常抛给调用方法,以使程序能够继续执行下去。用法:method()throws   Exception1,Exception2,。即throws用来声明一个方法可能会抛出的所有异常,如果一个方法声明的是受检异常,那么调用这个方法的类必须处理这个异常。可以使用try……catch……来捕获,也可以在该方法上声明throws。

public static void main(String[] args) {
        // TODO Auto-generated method stub
        int number = 0;
        try {
            System.out.println("aaaaaaaa");
            number = Integer.parseInt(args[0]);
            System.out.println("bbbbbbbb");
        } catch (Exception e) {
            // TODO: handle exception
            throw new ArrayIndexOutOfBoundsException("out of bounds");
            //System.out.println("非法的数字");
        }
        finally{
            System.out.println("你输入的数字为:"+number);
        }
    }  

结果:

  aaaaaaaa

  你输入的数字为:0

  Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: out of bounds

  at com.wt.others.ThrowTest.main(ThrowTest.java:12)

  原理:但抛出异常后将使用使用new在堆上创建异常对象,然后你的执行路径被终止,并且从当前环境中弹出对异常对象的引用,此时异常处理机制接管程序,并开始找一个恰当的地方执行程序,这个恰当的地方就是异常处理程序,它的任务就是将程序从错误状态中恢复。

public static void main(String[] args) {
        testThrows(args);
    }
    public static void testThrows(String[] tmp) {
        try {
            createThrows(tmp);
        } catch (Exception e) {
            // TODO: handle exception
            System.out.println("come from createThrows ");
        }
    }
    public static void test2Throws(String[] tmp) throws Exception {
        createThrows(tmp);
    }
    public static void createThrows(String[] tmp){
        int num = 0;
        num = Integer.parseInt(tmp[0]);
        System.out.println("你输入的数字为:"+num);
    }

  throws和throw可以组合在一起使用,就是在捕获异常后抛出一个明确的异常个调用者。

二者的区别:

  throw是用在方法中的,throws是用在方法签名之后的,在同一个地方使用这些的时候要注意,throws抛出异常的类型范围要比throw的大才行。

public static void main(String[] args) {
        try {
            methodA();
        } catch(Exception e)  {
            // TODO: handle exception
            System.out.println(e.getMessage());
        }
        methodB();
    }
    public static void methodA() {
        try {
            System.out.println("come in A");
            throw new RuntimeException("制造异常");
        } finally  {
            // TODO: handle exception
            System.out.println("用A的finally ");
        }
    }
    public static void methodB() {
        try {
            System.out.println("come in B");
            return;  //这里返回,在执行完finally语句后才返回
        } finally  {
            // TODO: handle exception
            System.out.println("用B的finally ");
        }
    } 

结果:

  come in A

  用A的finally 

  制造异常

  come in B

  用B的finally 

  3、getMessage和printStackTrace方法

  getMessage:返回此throwable对象的详细消息字符串

  printStackTrace:将此throwable对象及其追踪输出至标准错误流

try{
    fun();
}catch(Exception e){
    e.getMessage(e);
   // e.printStackTrace(e);
}

三、自定义异常类

  一般都选择Exception作为父类,如下:

public class MyException extends Exception{
    public MyException(){
        super();
    }
    public MyException(String msg){
        super(msg);
    }
    public MyException(Throwable cause){
        super(cause);
    }
    public MyException(String msg,Throwable cause){
        super(msg, cause);
    }
}

  

  其实并不是所有的异常都需要处理,异常处理会占用一定的资源,影响程序的执行效率。认真观察异常的名字和行号,尽量减少try语句块的体积,在处理异常的时候应该打印出该异常的堆栈信息以方便调试使用。

  对异常对象的清理并不需要过多的关心,因为他们都是用new在堆上建立的,垃圾回收器会自动将他们清理掉。

原文地址:https://www.cnblogs.com/silence-hust/p/4483951.html