我是靠谱客的博主 懵懂烧鹅,这篇文章主要介绍第七章《Java的异常处理》第1节:异常的概念及处理方式除阅读文章外,各位小伙伴还可以点击这里观看我在本站的视频课程学习Java!,现在分享给大家,希望可以做个参考。

Java语言被公认为是一种健壮性良好的语言,这主要是因为Java有一套科学合理的异常处理机制,这套处理机制可以保证程序在发生异常时能最大程度的恢复正常并继续执行。

7.1.1  异常的概念

“异常”一词从字面上理解就是“不正常”,而在Java编程中异常是指“运行时错误”。所谓“运行时错误”是指在代码没有任何语法错误的情况下,当程序实际运行时出现的错误。下面的例【07_01】就很好的展示了什么是运行时错误。

【例07_01 运行时错误】

Exam07_01.java

public class Exam07_01 {
    public static void main(String[] args) {
        int a = 0;
        int b;
        b=1/a; //①
        System.out.println("程序结束");//②
    }
}

【例07_01】的程序代码没有任何语法问题,但仔细观察程序不难发现:语句① 无法运行,因为任何数字都不能被0整除,而语句① 恰恰是做了1除以0的操作,因此程序在执行到语句① 时必然会出现错误,这个错误就是上文所说的“运行时错误”,“运行时错误”也被叫做“异常”。

当程序在运行过程中出现异常,虚拟机会创建出一个表示异常的对象,并且把异常信息保存到这个对象中。如果程序员没有对异常做任何处理,那么虚拟机会强行中止程序运行。【例07_01】的运行结果如图7-1所示。

图7-1 【例07_01】运行结果

从图7-1可以看出,程序并没有运行到语句② ,这说明这个程序已经被虚拟机强行中止。图7-1中出现了一些信息,这些信息就是异常信息。通常情况下,异常信息都会包含两部分内容:首先是异常出现的原因,其次是异常是在程序运行到哪一行代码时出现的。

7.1.2  异常的处理方式

为了不使程序在出现异常时就被强行中止,Java语言提供了非常科学的异常处理机制。处理异常需要用到两个关键字,分别是try和catch。try和catch代表两个块,程序员要把可能出现异常的代码写到try块中,而把处理异常的代码写到catch块中。catch块中的代码是异常出现时才被执行的,它如同是专门为异常准备的“紧急处理预案”,一旦try块中的代码在运行时出现异常,虚拟机就会跳转到catch块中执行代码。下面的【例07_02】展示了如何使用try和catch对异常进行处理。

【例07_02 异常处理】

Exam07_02.java

public class Exam07_02 {
    public static void main(String[] args) {
        int a = 0;
        int b;
        try {
            System.out.println("异常之前的语句");
            b=1/a;//①
            System.out.println("异常之后的语句");//②
        }catch(Exception e) {
            System.out.println("处理异常");
        }
        System.out.println("程序结束");//③
    }
}

【例07_02】由【例07_01】修改而来。在【例07_02】的代码中添加了try和catch块,try块中包含了可能出现异常的语句,而catch块中则是用来处理异常的语句。有读者会问:catch关键字后面的小括号中的“Exception e”是什么意思呢?上文讲过:虚拟机会创建一个对象来表示当前出现的异常,而对象都属于某一个类,Exception就是异常类,而“Exception e”表示声明了一个Exception类的引用e,这个引用会指向运行出错时虚拟机创建的那个异常对象,从而使程序员能够在catch块中通过引用e操作异常对象。【例07_02】的运行结果如图7-2所示。

图7-2 【例07_02】运行结果

图7-2中,控制台上输出的第2条信息是“异常处理”,这说明当语句① 运行出现异常时,程序会从try块跳转至catch块执行。而控制台上没有输出“异常之后的语句”,这可以说明异常处理的两个特点:首先,当异常出现时,虚拟机不会等到try块中所有代码都执行完才进入catch块,而是在异常出现时立刻进入catch块执行代码。其次,在catch块中处理完异常之后,程序不会再次重新回到try中执行代码。此外,控制台上输出了“程序结束”,这说明在这个程序中虽然出现了异常,但虚拟机并没有中止程序运行。虚拟机没有中止程序运行的原因是:当异常出现时,catch块成功的捕获到这个异常并做了相应的处理。虚拟机认为既然程序能够发现并妥善处理异常,就无需强行中止程序运行。

实际开发过程中,有时会编写一些必须执行的代码。例如:读取数据库时无论是否发生异常最终都要断开连接。如何保证某些代码在无论有没有发生异常的情况下都能得到执行呢?Java语言提供了一个finally关键字,这个关键字也代表一个块,开发者只需要把必须执行的代码写到finally快中就能保证这些代码一定能得到执行。下面的【例07_03】展示了finally关键字的作用。

【例07_03 finally关键字的使用】

Exam07_03.java

public class Exam07_03 {
    public static void main(String[] args) {
        int a = 0;
        int b;
        try {
            System.out.println("异常之前的语句");
            b=1/a;//①
            System.out.println("异常之后的语句");//②
        }catch(Exception e) {
            System.out.println("处理异常");
        }finally {
            System.out.println("一定会执行的代码");
        }
        System.out.println("程序结束");//③
    }
}

【例07_03】中,在catch块之后又添加了finally块,并在这个块中输出“一定会执行的代码”。【例07_03】的运行结果如图7-3所示。

图7-3 【例07_03】运行结果

图7-3中,控制台在输出“异常处理”的字样之后又输出了“一定会执行的代码”,这说明finally块中的代码在异常产生之后仍然能够得到执行。各位读者也可以把程序中变量a的值修改为1,验证一下在程序不产生异常时finally块中的代码也能执行。

在本书的4.2小节中曾经讲过:当程序运行到return语句时方法就立刻结束执行。当程序在finally块中的代码执行之前就遇到return语句时,finally块中的代码还能否得到执行呢?下面的【例07_04】能够证明:即使在finally块之前遇到return语句,finally块中的代码仍然能执行。

【例07_04 finally与return】

Exam07_04.java

public class Exam07_04 {
    public static void main(String[] args) {
        int a = 0;
        int b;
        try {
            System.out.println("异常之前的语句");
            b=1/a;
            System.out.println("异常之后的语句");
        }catch(Exception e) {
            System.out.println("处理异常");
            return;//①
        }finally {
            System.out.println("一定会执行的代码");
        }
        System.out.println("程序结束");//②
    }
}

【例07_04】在catch块中添加了return语句。【例07_04】的运行结果如图7-4所示。

图7-4 【例07_04】运行结果

程序运行出现异常,因此进入catch块中执行。从图7-4可以看出:由于catch块中有return语句,所以main()方法本应该在catch块中结束,但catch块中后面还有finally块,因此虚拟机会暂时不结束main()方法,而是先把finally块中的代码执行完毕,然后才结束main()方法的运行。从图7-4还可以看出,语句②并没有被执行,这说明虚拟机在执行完finally块中的代码之后,并不会继续执行后面的代码,而是立即转向执行之前遇到的return语句,因为在遇到return语句时,虚拟机仅仅允许finally块中的代码完成执行,其他代码都没有执行机会。

在Java语言中,try块不能单独出现,它必须搭配catch块或finally块,也可以二者全部搭配,就像【例07_03】和【例07_04】展示的那样。如果try块仅搭配了finally块,那么在程序运行出现异常时,虽然仍然能够保证finally块中的代码得到执行,但虚拟机还是会中止程序,请看【例07_05】:

【例07_05 没有catch块的异常程序】

Exam07_05.java

public class Exam07_05 {
    public static void main(String[] args) {
        int a = 0;
        int b;
        try {
            System.out.println("异常之前的语句");
            b=1/a;
            System.out.println("异常之后的语句");
        }finally {
            System.out.println("一定会执行的代码");
        }
        System.out.println("程序结束");//①
    }
}

【例07_05】的运行结果如图7-5所示。

图7-5 【例07_05】运行结果

从图7-5可以看出,虽然在出现异常时finally块中的代码能够被执行,但main()方法中最后出现的语句①并没有被执行,这说明在执行完finally块中的代码后虚拟机还是立刻中止了程序运行。虚拟机之所以强行中止程序,就是因为整个程序中没有用来捕获和处理异常的catch块。虚拟机认为只要出现了异常,并且没有对异常进行任何处理,就必须中止程序运行。

以上所有例子中,每次产生异常时都只是输出了“处理异常”,并没有真正对异常进行处理。实际上,如何处理异常是一件比较复杂的事情,要根据软件的类型和功能来确定。但是无论什么类型或功能的软件,在出现异常之后都应该显示出异常信息以便程序员对异常代码进行调试和修改。通常情况下,程序员在处理异常的过程中都会调用异常对象的printStackTrace()方法来显示异常的类型和出现的位置。printStackTrace()是一个打印异常信息的方法,在多个程序中出现方法多层次调用的情况下,这个方法还能显示出异常在每一个方法中出现的位置,下面的【例07_06】展示了printStackTrace()方法的作用:

【例07_06 printStackTrace()方法的使用】

Exam07_06.java

public class Exam07_06 {
    public static void test() {
        int a = 0;
        int b;
        b=1/a;
    }

    public static void main(String[] args) {
        try {
            test();
        }catch(Exception e) {
            e.printStackTrace();
        }
    }   
}

在【例07_06】的Exam07_06类中,除main()方法外还有一个test()方法,并且main()方法调用了test()方法。异常本来出现在test()方法中,但test()方法并没有对异常进行任何处理。main()方法在调用test()方法时,在其外围添加了try块来监控异常,并且在与其匹配的catch块中调用异常对象e 的printStackTrace()方法打印异常信息。【例07_06】的运行结果如图7-6所示。

图7-6 【例07_06】运行结果

图7-6中,第1行输出语句的“java.lang.ArithmeticException”指明了异常的类型,而“/ by zero”指出异常产生的原因是数字被0整除。第2行输出了“at Exam07_06.test(Exam07_06.java:5)”。此信息指出异常出现在Exam07_06类的test()方法中,并具体指明了出现异常代码的位于在Exam07_06类的第5行。第3行输出了“at Exam07_06.main(Exam07_06.java:9)”。这条信息说明main()方法在第几行调用了产生异常的test()方法,也可以理解为main()方法是在执行第几行代码时出现了异常。通过这个例子可以看出,printStackTrace()方法能够展示详细的异常信息。各位读者在实际开发过程中,一定要在catch块中调用异常对象的printStackTrace()方法,这样就可以轻松的确定异常的类型和产生位置。编程中最忌讳在catch块中不写任何语句,这会导致程序员无法察觉到异常已经产生,更不用说快速定位异常出现的位置。

除阅读文章外,各位小伙伴还可以点击这里观看我在本站的视频课程学习Java!

最后

以上就是懵懂烧鹅最近收集整理的关于第七章《Java的异常处理》第1节:异常的概念及处理方式除阅读文章外,各位小伙伴还可以点击这里观看我在本站的视频课程学习Java!的全部内容,更多相关第七章《Java内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(59)

评论列表共有 0 条评论

立即
投稿
返回
顶部