Java Exception

2018-08-05  本文已影响21人  sunpy

介绍

异常就是阻止当前方法或者作用域继续执行的错误。java中的异常主要分为Error异常和Exception异常。两个都继承自Throwable。
       Error异常主要是用来表示编译时和系统中的错误。
       Exception异常指一般的可以抛出的异常,这类异常需要通过程序去捕获然后进行处理。Exception异常通常是java程序员关心的。

Java异常终止模型

Java本身支持终止模型。程序从某一个小点发生异常,那么程序将无法回调异常发生的地方继续执行。意思就是一旦异常抛出,那么就标明错误已经无法挽回了,也不能回来继续执行了。这样就需要我们对于可能发生的异常做假设。

public class Dog {

    public static void main(String[] args) {
        String str = null;
        System.out.println(str.charAt(0));
        System.out.println("123456");
    }
}

结果:


1.jpg

解释:可以发现程序抛出空指针异常,然后程序终止,打印123456也执行。

Java异常捕获

前面提到了Java的终止模型,需要我们自己对可能发生的异常进行捕获。

    public static void main(String[] args) throws Exception {
        try {
            int i  = 3 / 0;
        } catch (ArithmeticException e) {
            throw new RuntimeException(e);
        } finally {
            System.out.println("123456");
        }
    }
2.jpg

解释:此处除数为0,然后抛出算术异常。

  1. Java异常链,在我们捕获异常时,想抛出一个新的异常,希望把原始异常信息保存下来,最终向上层传递,统一处理,这条链叫异常链。现在Throwable的子类都需要传递一个Throwable对象作为参数。通过这个对象将原始异常传递给新的异常,这样就可以保证虽然当前位置创建抛出新的异常,但是通过这个新的异常也可以找回原始的异常。
  2. finally子句作用,可以保证不管异常怎样执行,finally子句一定会执行。这样就可以保证,我们在发生异常时,依然可以关闭流等操作。
    finally注意的点:
    ① return中使用finally:因为finally语句一定会执行,所以我们可以在方法中写多个返回。
public class Dog {

    public static void eatFood(int foodType) {
        try {
            if (foodType == 1) {
                return;
            }
        } finally {
            System.out.println("123456");
        }   
    }
    
    
    public static void main(String[] args) throws Exception {
        eatFood(1);
    }
}

结果:


3.jpg

② break中使用finally:因为finally语句一定会执行,所以虽然在while语句中写finally语句,跳出循环,finally语句也会执行。

    public static void main(String[] args) throws Exception {
        while (true) {
            try {
                break;
            } finally {
                System.out.println("123456");
            }
        }
    }

结果:


4.jpg

异常匹配顺序

当系统抛出异常时,系统处理异常会按照程序的顺序找出最近的处理程序。找到匹配的处理程序进行处理异常之后,就不查找了。

public static void main(String[] args) throws Exception {
        try {
            int i = 3 / 0 ;
            String str = null;
            str.charAt(0);
        } catch(NullPointerException e) {
            throw new RuntimeException(e);
        } catch(ArithmeticException e1) {
            throw new RuntimeException(e1);
        }
    }
5.jpg

解释:
通过例子可以发现,空指针异常虽然在代码上是距离除数为0的最近处理程序。但是却不是匹配的处理程序。并且还可以看出当抛出算术异常时,程序将终止,将不会向继续查找空指针异常。

异常丢失的BUG

当我们在finally语句中抛出了异常,那么之前捕获的异常将会被取代,编程时需注意。

    public static void main(String[] args) throws Exception {
        try {
            int i = 3 / 0;
        } catch (ArithmeticException e) {
            throw new RuntimeException(e);
        } finally {
            String str = null;
            str.charAt(0);
        }
    }

结果:


6.jpg

解释:可以发现finally中的空指针异常取代了之前捕获的算术异常。

Excpetion和Error的区别

Error:主要是系统出错,jvm处于非正常的状态,这点我们是无法控制的,譬如NoClassDefFoundErr。
Exception:主要分为两类,一个是可以在编译器检查出的异常,譬如:IOException、InterruptedException;还有一个是不可检查的异常,譬如:空指针异常,下标越界异常,而这类异常也可以说是运行期异常RuntimeException。
在网上找到一张图:


异常图.jpg

经典面试题

NoClassDefFoundError 和 ClassNotFoundException区别
NoClassDefFoundError抛出的原因:
JVM在使用ClassLoader来实现类加载时,在类路径上没有找到对应的class文件。而最终的原因就是在jvm运行时期,没有加载到jar包中的类.class。
ClassNotFoundException抛出的原因:
spring中配置不好会经常抛出这个错误,主要是因为spring通过类名采用反射的方式Class.forName来加载类,jvm在类路径上没有找到类名对应的类,那么就会抛出这个异常。

上一篇下一篇

猜你喜欢

热点阅读