Java异常处理机制

来源:互联网 发布:淘宝网30天后执行冻结 编辑:程序博客网 时间:2024/05/18 00:45

异常是 一个类class
java.lang.Exception

异常分为两种:
a) Checked exception (非 Runtime Exception) 非运行时异常
b) Unchecked exception(Runtime Exception) 运行时异常

异常的继承关系:
1. Java中所有的异常类都会直接或间接地继承自Exception。
2. RuntimeException类也是直接继承自 Exception类,它叫做运行时异常,Java中所有的运行时异常都会直接或间接地继承自 RuntimeException。
3. Java 中凡是继承自 Exception 而不是继承自 RuntimeException 的类都是非运行时异常。

异常常用的一个方法 printStackTrace() 打印这个异常的信息

异常是一个类,当程序捕获了一个异常时,会动态的为这个异常生成一个异常对象

异常处理的第一种方式:

异常处理的一般结构是: 下面是个普遍的结构,还有许多变形
try {
}
catch(Exception e) {
}
finally {
}

如果try块中没有出现异常,那么catch中的语句是不会被执行的

无论程序是否出现异常,finally 块中的代码都是会被执行的。 (有一些特殊情况不会被执行,在下面有详细的内容)

注意的变形的是:
1. try{} catch{} finally{} 是可以的
2. try{} catch(){ } 是可以的,
3. try{} finally{ } 编译没问题的,但是运行的时候相当于没有对异常进行处理,所以 finaaly快执行完之后,程序就终止了,后面的代码就不会再被执行,在下面的例子中意味着 这一句 System.out.println(“我最后输出”) 不会被执行了
4. try { } catch{} catch{}…. 一个try块可以跟着很多catch块,但是最终只有一个catch快会被执行 ,但是一个try快只能跟着一个finally块,不能有多个finally块。

一般来说finally 快都是会被执行的,但是有一些特殊情况除外:

  1. 在try 或者catch 块中出现了 system.exit(0)(正常终止), system.exit(1)(异常终止) 程序强制退出,则finally快不会被执行。需要谨记的一点, 在try 或者catch 块中出现了return 并不会影响finally快的执行,但是finally块之后的内容就不会被执行了。
    try{            int a = 3;            int b = 0;            c = a / b;              System.out.println("我执行了吗?");  // 这一句没有被执行        }        catch(Exception e){            e.printStackTrace();  // 打印异常的信息            return;        }        finally{            System.out.println("我都会被执行");  // 都会被执行        }        System.out.println("我最后输出");   // 不会被执行
  1. try语句没有被执行到,如在try语句之前return就返回了,这样finally语句就不会执行。这也说明了finally语句被执行的必要而非充分条件是:相应的try语句一定被执行到 。
  2. 多线程里面也会出现finally块不会被执行的情况:
 @Override        public void run() {            // TODO Auto-generated method stub            try{                System.out.print("Starting ADaemon");                TimeUnit.MILLISECONDS.sleep(1);            }catch(InterruptedException e){                System.out.print("Exiting via InterruptedException");            }finally{                System.out.print("the finally really run?");            }        }    

一个例子说明了异常的一些情况:

public class ExceptionTest {    public static void main(String[] args) {        int c = 0;        try{            int a = 3;            int b = 0;            c = a / b;  // 发生了异常,动态的生成一个异常对象,然后跳出 try 块,后面的不再执行            System.out.println("我执行了吗?");  // 这一句没有被执行        }catch(Exception e){            e.printStackTrace();  // 打印异常的信息        } finally{            System.out.println("我都会被执行");  // 都会被执行        }        System.out.println("我最后输出");  // 因为前面进行了异常处理,所以会执行        int a = 3;        int b = 0;        c = a / b;   //  发生了异常,但是没有对其进行处理,因此程序终止,下面的语句不再执行        System.out.println(c); //  这一句不会被执行    }}

异常处理的第二种方式: throw 和 throws
throw 和 throws:抛出异常 throw 写在方法内部,throws 写在方法声明上,当方法里的异常向外抛的时候,它会抛向调用它的函数里,如何调用的函数没有进行处理,则继续向上抛,一直到达main方法,如果main方法也没有处理,则交由JVM处理

    public static void method() throws Exception {        // TODO Auto-generated method stub        System.out.println("抛出异常之前");        if (true){              throw new Exception();   // 程序抛出了异常之后,后面的代码也就不执行了              //  而且编译器也不允许你在后面再添加语句了,后面这一句输出添加到代码上会报错             // System.out.println("抛出异常之后");        }        System.out.println("抛出异常之后"); // 不会被执行    }

对于非运行时异常(checked exception) ,必须要对其进行处理,处理方式有两种:
第一种是使用 try.. catch…finally 进行捕获;
第二种是在调用该会产生异常的方法所在的方法声明 throws Exception
对于运行时异常(runtime exception) ,我们可以不对其进行处理,也可以对其进行处理。 推荐不对其进行处理。

需要注意的是: 不管是运行时的异常,还是非运行时的异常,如果一直往外抛异常,到了main函数里面还没有被处理,则程序会终止,下面的语句不会被执行。

NullPointerException 是空指针异常,该异常在编程的过程中会经常出现, 出现该异常的原因在于某个引用为 null,但你却调用了它的某个方法。这时就会出现该异常。

自定义的异常:实现比较简单,只要实现两个构造方法就可以,里面写一句 super()

// 自定义一个异常,定义构造方法就行,它会一层一层向上传public class MyException extends  RuntimeException{    public MyException () {        // TODO Auto-generated constructor stub        super();    }    public MyException (String message) {        // TODO Auto-generated constructor stub        super(message);    }}// 自定义一个异常,定义构造方法就行,它会一层一层向上传public class MyException2 extends  RuntimeException{    public MyException2 () {        // TODO Auto-generated constructor stub        super();    }    public MyException2 (String message) {        // TODO Auto-generated constructor stub        super(message);    }}

主要注意的一点:
我们可以使用多个 catch块来捕获异常,这时需要将父类型的 catch块放到子类型的catch 块之后,这样才能保证后续的 catch 可能被执行,否则子类型的 catch 将永远无法到达,Java 编译器会报编译错误;如果多个 catch 块的异常类型是独立的 (MyException, MyException2 ), 那么谁前谁后都是可以的。 因为异常的匹配是从前往后匹配的,当父类的catch放前面的时候,一个子类的异常也可以被父类捕获到,后面的就不会再被执行了。

这里写图片描述

0 0
原创粉丝点击