Java学习笔记(异常处理)

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 block
			HandlingSomething.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-1
				HandlingSomething.DoA2(); //A2-1
				HandlingSomething.DoA1(); //A1-1
			} catch (ExceptionA1 e) {
				HandlingSomething.PrintMsg(e.getMessage());//A1-2
			} catch (ExceptionA e) {
				// 这里从新抛出只是为了演示finally块一定会被执行.
				// 继续抛出
				HandlingSomething.PrintMsg("继续跑出2");//A2-2
				throw 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-5
			throw 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的编译器就会报编译错误。
当然事情都是两面性的,在编译期就保证异常得到正确的处理当然是好事,但这种机制也会带来一些问题,一是如果调用关系复杂,异常比较多,代码看起来就不那么纯粹,
会稍显凌乱;二是对程序员的要求会比较高,特别是在写牵扯到事务的底层代码时,程序员必须非常谨慎的对待异常的处理,不能屏蔽上层调用的事务机制。除非必要,对于涉及到事务机制的代码中的异常应该尽量抛给调用者去处理。


 

你可能感兴趣的:(Java学习笔记(异常处理))