Java学习笔记(异常处理)

来源:互联网 发布:mac怎么关闭隐藏文件 编辑:程序博客网 时间:2024/05/22 03:06

1) 异常处理机制
    在程序运行过程中,如果某条语句执行出现意外(比如,零除错误,IO错误等),那么Java的虚拟机就会停下,不会继续执行后续的语句,而是由里到外(因为一个方法内部,异常捕获是可以嵌套的),沿被调用关系寻找异常处理模块,如果:
A) 最终找到异常处理模块,则转而执行异常处理模块中的语句,异常处理语句执行完成后,则继续执行异常处理模块的后续语句(可能是finally模块),如下:

public class ExceptionTest {public static void main(String[] args) throws Exception {try {CallSomeMethods.DoA1();} catch (ExceptionA e) {// TODO Auto-generated catch blockHandlingSomething.PrintMsg(e.getMessage());//A2-7}System.out.println("执行完毕!");//A1-7,A2-8}}class ExceptionA extends Exception{public  ExceptionA() {super("ExceptionA");}public  ExceptionA(String Msg) {super(Msg);}}class ExceptionA1 extends ExceptionA{public  ExceptionA1() {super("ExceptionA1");}}class ExceptionA2 extends ExceptionA{public  ExceptionA2() {super("ExceptionA2");}}class CallSomeMethods{public static void DoA1() throws Exception {// 1 异常处理代码模块开始try {// 2异常捕获代码块开始try {//要测试哪个异常,请把产生该异常的语句放在前面HandlingSomething.DoA3(); //A3-1HandlingSomething.DoA2(); //A2-1HandlingSomething.DoA1(); //A1-1} catch (ExceptionA1 e) {HandlingSomething.PrintMsg(e.getMessage());//A1-2} catch (ExceptionA e) {// 这里从新抛出只是为了演示finally块一定会被执行.// 继续抛出HandlingSomething.PrintMsg("继续跑出2");//A2-2throw new ExceptionA(e.getMessage()+":继续跑出2");//A2-3} finally {HandlingSomething.PrintMsg("这里总会执行1");//A1-3,A2-4,A3-2}// 2异常捕获代码块结束// 2异常后续语句,如果前面的异常被处理而又没有抛出新的异常就会被执行。System.out.println("这是异常捕获处理模块2的后续语句"); //A1-4} catch (ExceptionA e) {// 继续抛出HandlingSomething.PrintMsg("继续跑出1");//A2-5throw new ExceptionA(e.getMessage()+":继续跑出1");//A2-6}finally{HandlingSomething.PrintMsg("这里总会执行2");//A1-5,A2-7,A3-3}// 1 异常处理代码模块结束// 1异常后续语句,如果前面的异常被处理而又没有抛出新的异常就会被执行。HandlingSomething.PrintMsg("这是异常捕获处理模块1的后续语句");//A1-6}}class HandlingSomething{//这里为了演示,所以只简单的抛出异常public static void DoA1() throws ExceptionA1{    throw new ExceptionA1();}//这里为了演示,所以只简单的抛出异常public static void DoA2() throws ExceptionA2{    throw new ExceptionA2();}public static void DoA3() throws Exception{throw new Exception("这个异常不处理!");}synchronized public static void  PrintMsg(String Msg) {SimpleDateFormat theA =new SimpleDateFormat("yyyyMMddHHmmss");System.out.println(Msg+":"+ theA.format(new java.util.Date()));}}


B)如果找不打异常处理块,最后会由Java虚拟机进行处理,是否会结束程序,要看具体的程序和具体的异常,上述测试DoA3时是会结束程序的。
Java和C#的异常处理机制也是典型的责任链模式。
2) 捕获方式
   用try块将可能产生异常的代码包含起来,接着就是异常匹配处理块,异常匹配处理块可以有多个,注意:
   异常匹配是按顺序进行的,找到匹配的异常处理块后,后面的匹配就会放弃匹配,因此在书写匹配块时,在异常类继承体系中,层次越低的放在前面,
   层次越高的在后面。因为异常匹配不是精确匹配优先,而是匹配顺序优先,匹配只要满足“是”关系就可以了,也就是如果一个异常类是A,那么A及A的
所有子异常类都能在异常类A匹配的地方得到匹配。

3) 比较:
   与C#相比,Java的异常处理机制更加严谨一些,它要求你对可能的异常A要么处理,要么显示的向调用者声明你没有处理异常A,否则Java的编译器就会报编译错误。
当然事情都是两面性的,在编译期就保证异常得到正确的处理当然是好事,但这种机制也会带来一些问题,一是如果调用关系复杂,异常比较多,代码看起来就不那么纯粹,
会稍显凌乱;二是对程序员的要求会比较高,特别是在写牵扯到事务的底层代码时,程序员必须非常谨慎的对待异常的处理,不能屏蔽上层调用的事务机制。除非必要,对于涉及到事务机制的代码中的异常应该尽量抛给调用者去处理。


 

原创粉丝点击