笔试题
java处理异常采用try-catch-finally语句捕获处理异常,finally常用来处理一些后续的工作,今天遇到了一个很容易错的知识点,我觉得有必要写点东西做一个总结。
先提一下return语句的用法,return不管是在c/c++语言还是在java中都是返回函数值的语句。我们都知道return语句的一般作用:
(1)给调用方返回一个值;
(2)结束当前的方法(退出当前方法的调用栈)。
并且当一个方法中有多个return时,会按照执行的顺序只执行第一个return,当然最终的函数返回值也是第一个return值。因为当执行第一个return语句后该方法就运行结束了。
那么问题来了:
请看下面的一个java的代码,读者也可先预想一下结果:
public class Test {
public static void main(String[] args) {
System.out.println(test(null) + "," + test("0") + "," + test(""));
}
public static int test(String str) {
try {
return str.charAt(0) - 48; //将字符转为数字,48是'0'的十进制数值
} catch (NullPointerException e1) {
return 1;
} catch (StringIndexOutOfBoundsException e2) {
return 2;
} catch (Exception e3) {
return 3;
} finally {
return 4;
}
}
答案是: 4,4,4
不知道你有没有做对,反正我是做错了,惭愧。
下面附上执行的结果(添加了异常信息的输出方法的结果,方便查看):
java.lang.NullPointerException
at cn.test.example.Test.test(Test.java:14)
at cn.test.example.Test.main(Test.java:9)
java.lang.StringIndexOutOfBoundsException: String index out of range: 0
at java.lang.String.charAt(String.java:646)
at cn.test.example.Test.test(Test.java:14)
at cn.test.example.Test.main(Test.java:9)
4,4,4
输出结果分析:
- (1) java中的finally语句首先在所有catch的后面,其次他是必须执行的,无条件执行的,即使前面的try-catch语句中已经存在异常了,它仍然会执行。
- (2) 最然后不明白的就是当调用 tets(“null”)时会有NullPointerException类型的异常,但他还是会执行后面return 1;按照常理来说,运行到此处的return该方法就应该退出调用栈并且整个方法结束,但是看结果显示不是。
那么,catch中的return语句有两种情况:- 运行了,但是没有让当前函数的调用结束:
- 没有执行:这种推测有疑问就是,虚拟机的pc(程序计数器)是按顺序执行的,如果catch语句被执行,那么他内部的return语句也应该被执行,除非程序运行到catch语句就已经知道里面是return语句,但是这种运行方式需要提前知道我们是有写finally语句的
一般遇到这样的问题,可能就不能停留在源码层面上了,得考虑考虑jvm对我们的程序做了什么,我们不如反编译一下class字节码,看看有什么特殊处理没,下面是我反编译的字节码代码:
public static int test(String str) {
try {
boolean var2;
try {
int var1 = str.charAt(0) - 48;
return 4;
} catch (NullPointerException var8) {
var2 = true;
return 4;
} catch (StringIndexOutOfBoundsException var9) {
var2 = true;
return 4;
} catch (Exception var10) {
var2 = true;
return 4;
}
} finally {
;
}
}
这下就能看出来了,原来jvm做了处理,finally中的return语句压根没被执行,三个catch语句中的return全都变成finally里面的return语句了,至于为什么这样做,等懂jvm编译原理的大佬来回答了。哈哈哈
- 结论:
- (1) 在try-catch-finally语句中,finally语句是必须执行的,
- (2) 如果finally中有return语句,所有catch语句中的return语句将会被finally语句中的return语句代替,等价于finally语句中的return才是函数真正的return语句。
等价于变成下面这样代码
public static int test(String str) {
int j;
try {
int i = str.charAt(0) - '0';
return 4;
} catch (NullPointerException e1) {
e1 = e1;
j = 1;
} catch (StringIndexOutOfBoundsException e2) {
e2 = e2;
j = 2;
} catch (Exception e3) {
e3 = e3;
j = 3;
} finally {
}
return 4;
}
虽然是个小问题,但是比较容易出错,所以在此作以说明。
转载请说明出处:http://blog.csdn.net/yyg_2015/article/details/52188066