java中的finally用法

笔试题
 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

发布了31 篇原创文章 · 获赞 6 · 访问量 4万+
展开阅读全文

java.lang.StringIndexOutOfBoundsException报错的原因?

01-12

while (stringBuffer.indexOf("AAC1") != -1 && stringBuffer.indexOf("EEED") != -1) {                     LogUtil.logShipment(TAG, "AA 接受到的数据: " + stringBuffer.toString());                     if (stringBuffer.indexOf("AAC1", 0) < (stringBuffer.indexOf("EEED", 0) + 4)){                         String s = stringBuffer.substring(stringBuffer.indexOf("AAC1",0),stringBuffer.indexOf("EEED",0) + 4);                         if (s != null && !s.isEmpty()) {                              mHandler.post(new ScanEndRunnable(s));                             stringBuffer.delete(stringBuffer.indexOf("AAC1", 0), stringBuffer.indexOf("EEED", 0) + 4);                         }                     } else {                         stringBuffer.delete(0, stringBuffer.indexOf("AAC1", 0));                     }                 } 报错如下 java.lang.StringIndexOutOfBoundsException: length=0; regionStart=-1; regionLength=4         at java.lang.AbstractStringBuilder.startEndAndLength(AbstractStringBuilder.java:211)         at java.lang.AbstractStringBuilder.substring(AbstractStringBuilder.java:616)         at java.lang.StringBuffer.substring(StringBuffer.java:718) String s = stringBuffer.substring(stringBuffer.indexOf("AAC1",0),stringBuffer.indexOf("EEED",0) + 4);为什么会报这种错呢?代码哪出问题了? 问答

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 精致技术 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览