异常处理机制

一、什么是异常

java的基本理念是“结构不佳的代码不能运行”,在编译期间并不能发现所有的错误,余下的问题必须在运行阶段解决。异常处理是java中唯一正式的错误报告机制。异常情形是指阻止当前的方法或者作用域继续执行的问题。在java中通过异常处理机制来处理程序运行期间出现的错误,提升程序的健壮性。

java中与使用其他对象一样,在堆上创建对象来处理异常。针对不同的异常new出不同的异常对象。异常对象的根类是java.lang.Throwable类。在Java中定义了很多异常类(如OutOfMemoryError、NullPointerException、IndexOutOfBoundsException等),这些异常类分为两大类:Error和Exception。Error即无法处理的异常,一旦发生终止程序的运行。Exception,是我们可以处理的异常。Exception包括hecked exception和unchecked exception两类。

unchecked exception(非检查异常),也称运行时异常(RuntimeException),比如常见的NullPointerException、IndexOutOfBoundsException。对于运行时异常,java编译器不要求必须进行异常捕获处理或者抛出声明,由程序员自行决定。

checked exception(检查异常),也称非运行时异常(运行时异常以外的异常就是非运行时异常),java编译器强制程序员必须进行捕获处理,比如常见的IOExeption和SQLException。对于非运行时异常如果不进行捕获或者抛出声明处理,编译都不会通过。

在Java中,异常类的结构层次图如下图所示:

在Java中,所有异常类的父类是Throwable类,Error类是error类型异常的父类,Exception类是exception类型异常的父类,RuntimeException类是所有运行时异常的父类,RuntimeException以外的并且继承Exception的类是非运行时异常。常见的异:NullPointerException、IndexOutOfBoundsException、ArrayIndexOutOfBoundsException等等。

异常匹配:抛出异常的时候,异常处理系统会按照代码的书写顺序找出“最近”的处理程序,找到匹配的处理程序后,则认为异常得到了处理,然后不再继续查找。查找的时候并不要求抛出的异常同处理程序声明的异常完全匹配,派生类对象匹配其基类的处理程序。那么Exception则是所有的异常类的基类,即可捕获所有的异常。

把“受检查异常“转换为“不受检查的异常”,可以在捕获到的受检查异常后,再次抛出一个不受检查的异常。

二、异常的处理处理方式

1、捕获

异常的捕获主要使用try和catch关键字,被try块包围的代码,表示这段代码中可能出现异常,一旦发生异常,异常对象则被cathch捕获,然后在catch块中进行处理。如下:

 1 public class Demo5 {
 2     public static void main(String[] args) {
 3         try {
 4             int i=10/0;
 5             System.out.println(i);
 6         } catch (ArithmeticException e) {
 7             e.printStackTrace(System.err);
 8         }
 9     }
10 }
11 输出的结果:
12 java.lang.ArithmeticException: / by zero
13     at com.sun.lp.demo.Demo5.main(Demo5.java:18)

2、抛出

抛出是异常处理的另外一种方式,顾名思义,一旦发生异常,将异常抛出去,处理的关键字是throw和throws,如下:

public class Demo5 {
    public void test() throws Exception{
        try {
            int i = 10/0;
            System.out.println(i);
        } catch (Exception e) {
            //捕获到异常,不处理,将其抛出
            throw e;
        }
        
    }
    public static void main(String[] args) {
        try {
            Demo5 demo5 = new Demo5();
            demo5.test();
        } catch (Exception e) {
            e.printStackTrace(System.err);
        }
        
        
    }
    
}

结果输出:

java.lang.ArithmeticException: / by zero
    at com.sun.lp.demo.Demo5.test(Demo5.java:6)
    at com.sun.lp.demo.Demo5.main(Demo5.java:17)

三、自定义异常

不拘泥于java中已有的异常对象,java提供的异常体系不可能预见所有的异常。所以java提供自定义异常的途径。自定义异常必须从已有异常类的基础上继承和拓展。建立新的异常最简单的方法是让编译器为你产生默认的构造器

 1 public class Demo {
 2 
 3     public void test() throws MyException{
 4         System.out.println("Exception is from test()");
 5         throw new MyException();
 6     }
 7     
 8     public static void main(String[] args) {
 9         try {
10             Demo demo = new Demo();
11             demo.test();
12         } catch (Exception e) {
13             System.out.println("get a Exception");
14             e.printStackTrace(System.err);
15         }
16         
17     }
18     
19 }
20 
21 class MyException extends Exception{
22     MyException(){
23         System.out.println("自定义异常类");
24     }
25 }

输出结果:

Exception is from test()
自定义异常类
get a Exception
com.test.demo.MyException
    at com.test.demo.Demo.test(Demo.java:5)
    at com.test.demo.Demo.main(Demo.java:11)
四、使用finally进行清理
对于一些代码,无论try块中的异常是否抛出,它们都能执行,达到这个效果可以使用finally子句。finally子句总能运行。
 1 public class FinallyDemo {
 2     public static int count=0;
 3     public static void main(String[] args) {
 4         while(true){
 5             try {
 6                 if(count++==0)
 7                     throw new SimpleException();
 8                 System.out.println("No Exception");
 9             } catch (SimpleException e) {
10                 System.out.println("get a SimpleException");
11             }finally{
12                 System.out.println("finally 子句执行");
13                 if(count==2) break;
14             }
15         }
16     }
17 }
18 class SimpleException extends Exception{
19     SimpleException(){
20         super();
21     }
22 }

输出结果:

get a SimpleException
finally 子句执行
No Exception
finally 子句执行

五、几个关键字的使用

1.try关键字用来包围可能会出现异常的逻辑代码,它单独无法使用,必须配合catch或者finally使用。三个块执行的顺序为try—>catch—>finally。Java编译器允许的组合使用形式只有以下三种形式:

try...catch...;       try....finally......;    try....catch...finally...

2.throws和thow关键字

throws出现在方法的声明中,表示该方法可能会抛出的异常,然后交给上层调用它的方法程序处理,允许throws后面跟着多个异常类型。

throw一般用于程序出现某种逻辑,程序员主动抛出指定的异常对象,throw主要出现在方法体中,抛出的异常对象可以进行向上转型。

3.由于垃圾回收机制的存在,finally主要是把除内存资源之外的资源恢复到它们的初始状态,例如:关闭文件流,网络联机,关闭数据库连接等等。

六、异常使用指南

1)在恰当的级别处理问题(在知道如何处理的情况下才捕获异常)

2)解决问题并重新调用产生异常的方法

3)进行少许的修补,然后绕过异常发生的地方继续执行

4)用别的数据进行计算,以代替方法预计会返回的值

5)把当前运行环境下能做的事情尽量做完,然后把相同的异常抛出到更高层

6)把当前运行环境下能做的事情尽量做完,然后把不相同的异常抛出到更高层

7)终止程序

8)进行简化

9)让类库和程序更安全。

原文地址:https://www.cnblogs.com/liupiao/p/9249232.html