下面是一段代码,做一下在各种情况下try{}catch{}finaly{}中做的操作对返回参数的影响。
int test1(){int x = 0;try{x = 1;System.out.println("-----1------");throw new Throwable();}catch (Exception e){x = 2;System.out.println("-----2------");return x;} finally {x = 3;System.out.println("-----3------");return x;}}
以上的代码输出结果是
-----1------
-----3------
test1()=3
说明即便是在cache中没有捕获到的异常,依旧会执行finaly中的代码。
static int test27(){int x = 0;int y = 0;try{x = 1;int a = x/y;System.out.println("-----1------");return x;}catch (Exception e){x = 2;System.out.println("-----2------");return x;} finally {x = 3;System.out.println("-----3------");}}
输出结果:
-----2------
-----3------
test27=2
说明在cache中捕获到的异常,在执行到catch中的return时,才会执行finaly中的代码。
int test1(){int x = 0;try{x = 1;System.out.println("-----1------");return x;}catch (Exception e){x = 2;System.out.println("-----2------");return x;} finally {x = 3;System.out.println("-----3------");}}
以上的代码输出结果是
-----1------
-----3------
test1()=1
说明方法在return之前会执行finaly中的内容,如果对finaly中对return的对象进行改变,是不会影响真正返回对象的值的,说明代码在执行到return时,已经用一个值returnValue来保存需要返回的值,这个值和原来的局部变量并不是同一个值。之后执行的finaly中的代码对局部变量的修改不影响返回的值。
以上是基本数据类型,下面试一下类和包装类的情况。
类:
static TestBean test28(){TestBean testBean = new TestBean();try{testBean.setName("111111");System.out.println("-----1------");return testBean;}catch (Exception e){testBean.setName("222222");System.out.println("-----2------");return testBean;} finally {testBean.setName("333333");System.out.println("-----3------");}}
结果是:
-----1------
-----3-----
test28() = TestBean(name=333333, age=0, date=null)
在finaly中创建新对象
static TestBean test28(){TestBean testBean = new TestBean();try{testBean.setName("111111");System.out.println("-----1------");return testBean;}catch (Exception e){testBean.setName("222222");System.out.println("-----2------");return testBean;} finally {testBean = new TestBean();testBean.setName("333333");System.out.println("-----3------");}}
-----1------
-----3-----
test28() = TestBean(name=1111111, age=0, date=null)
包装类:
static Integer test30(){Integer integer = null;try{integer = 1;System.out.println("-----1------");return integer;}catch (Exception e){integer = 2;System.out.println("-----2------");return integer;} finally {integer = 3;System.out.println("-----3------");}}
结果是:
-----1------
-----3------
test30()=1
包装类的结果是一样的。
从上面的的示例说明,
1. 对于基本数据类型(包括其包装类型)作为返回值时,代码在执行到return时,已经用一个值returnValue来保存需要返回的值,这个值和原来的局部变量并不是同一个值。之后执行的finaly中的代码对局部变量的修改不影响返回的值。
2. 对于对于引用数据类型,也就是对象作为返回值时,代码在执行到return时,返回值returnValue中记录的应该是返回对象的地址。finaly对这个对象的属性的修改依旧会影响其返回值。但是如果是对返回对象从新new分配(或者置为null),就不会影响返回值,因为已经记录了返回对象的地址。
java代码在编译成class之后会生成一个异常表(Exception table)。
这个异常表中记录在某些代码段出异常时要跳转到到哪一行开始执行代码。
Exception table的字段
from to target type
其中 from to type是class中一些命令的行数, type是异常类型,或者any。
表的含义是:如果在执行from到to的代码时,如果出现type类型的异常,就开始执行target位置的代码。如果target是any则在把返回参数returnValue推入栈顶之后开始执行any对应的target行开始的代码。