java异常

java异常

Java异常体系

在这里插入图片描述
Java异常体系的根类是 Throwable, 所以当写在java代码中写throw抛出异常时,后面跟的对象必然是Throwable或其子类的对象。

Error 类层次结构描述了 Java 运行时系统的内部错误和资源耗尽错误。 应用程序不应该抛出这种类型的对象。 如果出现了这样的内部错误, 除了通告给用户,并尽力使程序安全地终止之外, 再也无能为力了。这种情况很少出现。

在设计 Java 程序时, 需要关注 Exception 层次结构。 这个层次结构又分解为两个分支:
一个分支派生于 RuntimeException ; 另一个分支包含其他异常。划分两个分支的规则是:
由程序错误导致的异常属于 RuntimeException ;
而程序本身没有问题, 但由于像 I/O 错误这类问题导致的异常属于其他异常:
派生于 RuntimeException 的异常包含下面几种情况:

  • 错误的类型转换。
  • 数组访问越界 i
  • 访问 null 指针

不是派生于 RuntimeException 的异常包括:

  • 试图在文件尾部后面读取数据。
  • 试图打开一个不存在的文件。
  • 试图根据给定的字符串查找 Class 对象, 而这个字符串表示的类并不存在。

“ 如果出现 RuntimeException 异常, 那么就一定是你的问题” 是一条相当有道理的规则。
应该通过检测数组下标是否越界来避免 ArraylndexOutOfBoundsException 异常;应该通过在使用变量之前检测是否为 null 来杜绝 NullPointerException 异常的发。

unchecked异常

在上图中除了RuntimeException、Error及其子类都是属于unchecked的异常类型外,其他的都是受编译器checked检查的异常。

unchecked不受编译器检查的异常, 是因为这些错误在程序运行过程中是可以通过编程手段去控制住的,

例如常见的NullPointerException空指针异常和IndexOutOfBoundsException数组下标越界的异常,这些都可以事先使用if (xx != null) 以及 if (xxx.size() > i)来控制,

或者就是完全无法通过程序手段控制,

例如OutOfMemoryError内存溢出异常和StackOverflowError栈溢出异常,这种Error因为无法通过代码层面if就能避免的,所以也属于unchecked。

checked异常

checked在编译过程中受到编译器的检查,如果程序没有对该异常做catch处理或者向上一层抛出的话,程序将无法编译通过,

常见的checked异常有FileNotFoundException文件不存在异常等,因为这种异常在编写阶段就可以预见,例如这个文件极有可能是不存在的,所以这种异常必须要抛出并要求程序作出处理。

总结

Throwable任何异常/错误的祖先类,属于checked异常。

Exception异常,可以从异常中恢复执行的异常,属于checked异常。

RuntimeException异常,预料之外的异常例如空指针、数组越界,属于unchecked异常。

…Exception除了RuntimeException及其子类是unchecked异常,其他的Exception类都是checked异常。

Error错误,致命问题,无法从错误中恢复, 也属于unchecked异常。

在开发过程中,如果一些可以预料的到的错误抛出异常时,尽量抛出checked异常,例如那个文件、某个数据一定可能会不存在的情况下,就要提示该方法的调用者,需要对这种情况进行处理,

如果是一些预料之外的异常,则可以使用RuntimeException,例如某个值规定一定是必须不为空,但是程序判断时为空了,则要进行RuntimeException的抛出。

有关try…catch…finally执行顺序的题目

try用于包含运行时的代码块,第一步执行,

catch用于捕获代码运行时可能发生的异常,第二步执行

当代码块执行到某一步发生错误时,后面的代码将不会进行执行,

而是跳转到catch的代码块中,catch顺序由上而下,以第一个可以捕获到当前异常的catch进行执行其中的内容,

finally是程序不管有没有发生异常,这里的代码最终一定会执行,所以是第三步执行。

public class ClassFenXi {
    public static void main(String[] args) {
        System.out.println(hand(""));
    }
    public static int hand(String s){
        int n=0;
        try{
            n=1;
            Class<?> aClass=Class.forName(s);
            n=2;
            return n;
        }catch (Exception e){
            n=3;
            return n;
        }finally {
            System.out.println("执行了");
            n=4;
            //return n;
        }
    }
}

该程序的执行结果为
在这里插入图片描述
解释:
由于传入的参数为空的字符串,而不可能有名字为空的字符串的类,所以发生了异常
进入catch块,将n=3return。但是由于finally是程序不管有没有发生异常,这里的代码最终一定会执行
所以hand方法并没有在catch块return后就直接结束,而是等finally中的代码执行完之后才会结束。因此先执行了

finally {
            System.out.println("执行了");
            n=4;
            //return n;
        }

打印出了"执行了"虽然又将n赋值为4,但n=3时已经在catch块return了,所以最终的返回值为3
所以finally中的代码执行完成后,整个方法结束
返回main方法中执行System.out.println(hand(“”));打印出3

当在finally中加入return之后

public class ClassFenXi {
    public static void main(String[] args) {
        System.out.println(hand(""));
    }
    public static int hand(String s){
        int n=0;
        try{
            n=1;
            Class<?> aClass=Class.forName(s);
            n=2;
            return n;
        }catch (Exception e){
            n=3;
            return n;
        }finally {
            System.out.println("执行了");
            n=4;
            return n;
        }
    }
}

执行结果为
在这里插入图片描述
解释:
经过前面的分析,最后会执行finally中的代码。
而finally中的代码中有return n语句,这就将catch中的return语句覆盖了,因此返回的结果为4.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值