java异常捕获分析
    思考问题:
    调用下面的方法分别会返和输出回什么?
package com.itdragon.controller;
import org.junit.Test;
public class TestMain {
	public int test1() {
		int a=0;
		try {
			a=1/0;
		} catch (Exception e) {
			System.out.println("test1:err");
			a=100;
			return a;
		}finally {
			System.out.println("test1:fin");
			a=200;
			return a;
		}
	}
	public int test2() {
		int a=0;
		try {
			a=1/0;
		} catch (Exception e) {
			System.out.println("test2:err");
			a=100;
			return a;
		}finally {
			System.out.println("test2:fin");
			a=200;
		}
		return a;
	}
	
	@Test
	public void tests(){
		System.out.println("test1:"+test1());
		System.out.println();
		System.out.println("test2:"+test2());
	}
	
}	

    众所周知,java捕获到异常时,先执行catch 代码块,如果有finally代码块,那么无论最后有没有异常都会执行finally代码块。
    对于test1都好理解,最后在finally中返回,值为200.
    但是对于test2就有点难以理解,认为应该返回200,但是却返回了100.
    对于上述两个方法简化,在做叙述:
public int test1() {
		int a=0;
		try {
			a=1/0;
		} catch (Exception e) {
			a=100;
			return a;
		}finally {
			a=200;
			return a;
		}
	}
	public int test2() {
		int a=0;
		try {
			a=1/0;
		} catch (Exception e) {
			a=100;
			return a;
		}finally {
			a=200;
		}
		return a;
	}
    
反编译出的字节码如下:
test1
public int test1();
    descriptor: ()I
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=5, args_size=1
         0: iconst_0	//将int型0推送至栈顶  
         1: istore_1	//将栈顶int型数值存入第二个本地变量  
         2: iconst_1	//将int型1推送至栈顶 
         3: iconst_0	//将int型0推送至栈顶  
         4: idiv		//将栈顶两int型数值相除并将结果压入栈顶  
         5: istore_1	//将栈顶int型数值存入第二个本地变量  
         6: sipush        200	//将一个短整型常量值(-32768~32767)推送至栈顶 
         9: istore_1	//将栈顶int型数值存入第二个本地变量  
        10: iload_1		//将第二个int型本地变量推送至栈顶 
        11: ireturn		//从当前方法返回int  
        12: astore_2	//将栈顶引用型数值存入第三个本地变量
        13: bipush        100	//将单字节的常量值(-128~127)推送至栈顶
        15: istore_1	//将栈顶int型数值存入第二个本地变量  
        16: iload_1		//将第二个int型本地变量推送至栈顶 
        17: istore_3	//将栈顶int型数值存入第四个本地变量
        18: sipush        200	//将一个短整型常量值(-32768~32767)推送至栈顶 
        21: istore_1	//将栈顶int型数值存入第二个本地变量
        22: iload_1		//将第二个int型本地变量推送至栈顶 
        23: ireturn		//从当前方法返回int  
        24: astore        4		//将栈顶引用型数值存入指定本地变量
        26: sipush        200	//将一个短整型常量值(-32768~32767)推送至栈顶 
        29: istore_1	//将栈顶int型数值存入第二个本地变量
        30: iload_1		//将第二个int型本地变量推送至栈顶 
        31: ireturn		//从当前方法返回int  
      Exception table:
         from    to  target type
             2     6    12   Class java/lang/Exception
             2     6    24   any
            12    18    24   any
            24    26    24   any
test2:
 public int test1();
    descriptor: ()I
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=5, args_size=1
         0: iconst_0	//将int型0推送至栈顶
         1: istore_1	//将栈顶int型数值存入第二个本地变量	
         2: iconst_1	//将int型1推送至栈顶
         3: iconst_0	//将int型0推送至栈顶
         4: idiv		//将栈顶两int型数值相除并将结果压入栈顶
         5: istore_1	//将栈顶int型数值存入第二个本地变量
         6: sipush        200	//将一个短整型常量值(-32768~32767)推送至栈顶 
         9: istore_1	//将栈顶int型数值存入第二个本地变量
        10: goto          34	//无条件跳转
        13: astore_2	////将栈顶引用型数值存入第三个本地变量
        14: bipush        100	//将单字节的常量值(-128~127)推送至栈顶
        16: istore_1	// 将栈顶int型数值存入第二个本地变量
        17: iload_1		//将第二个int型本地变量推送至栈顶
        18: istore_3	//将栈顶int型数值存入第四个本地变量
        19: sipush        200	// 将一个短整型常量值(-32768~32767)推送至栈顶  
        22: istore_1	//将栈顶int型数值存入第二个本地变量 
        23: iload_3		//将第四个int型本地变量推送至栈顶
        24: ireturn		// 从当前方法返回int
        25: astore        4		//将栈顶引用型数值存入指定本地变量
        27: sipush        200	//将一个短整型常量值(-32768~32767)推送至栈顶  
        30: istore_1	//将栈顶int型数值存入第二个本地变量
        31: aload         4	//将指定的引用类型本地变量推送至栈顶 
        33: athrow		//将栈顶的异常抛出
        34: iload_1		//将第二个int型本地变量推送至栈顶
        35: ireturn		// 从当前方法返回int
      Exception table:
         from    to  target type
             2     6    13   Class java/lang/Exception
             2     6    25   any
            13    19    25   any
            25    27    25   any
        可能对于不是太了解字节码的同学来说不好理解。
        但是从中我的理解是:当有finally块存在的时候,虚拟机执行完catch块中的代码时不会立即返回,而是把return语句给屏蔽了,将catch中的代码执行完以、变量在局部变量表中保存好以后,继续执行finally块中的代码,如果finally块中有返回语句,则直接返回,否则,虚拟机去取在catch块中保存的局部变量,放入栈顶,返回。