`
ajaxgo
  • 浏览: 18464 次
  • 性别: Icon_minigender_1
  • 来自: 珠海
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

关于java中,try/catch执行的问题

阅读更多

今天无意中,同事发现了一个有趣的现象,首先来看一下以下代码:

java 代码会发现,18行加载了一下变量b中的值,所以,其实,在执行代码的第8行时,并不是执行return,而只是往内存中存储变量b的值。

  1. public class Test {   
  2.     private static int todo() {   
  3.         int b=1;   
  4.         try{   
  5.             int a=2/0;   
  6.         } catch(Exception e) {   
  7.             System.out.println("in catch");
  8.             return 1;   
  9.         } finally {   
  10.             System.out.println("in final");   
  11.         }   
  12.         return 2;   
  13.     }   
  14.     /**  
  15.      * @param args  
  16.      */  
  17.     public static void main(String[] args) {   
  18.         System.out.println(todo());   
  19.   
  20.     }   
  21. }  

此时,运行结果为
in catch
in final
1

看到这里,少部分人已经开始不明白了,我们继续看另一则代码(请注意细小的差别):

java 代码
  1. public class Test {      
  2.     private static int todo() {      
  3.         int b=1;      
  4.         try{      
  5.             int a=2/0;      
  6.         } catch(Exception e) {      
  7.             System.out.println("in catch");   
  8.             return b;      
  9.         } finally {      
  10.             System.out.println("in final");      
  11.         }      
  12.         return 2;      
  13.     }      
  14.     /**    
  15.      * @param args    
  16.      */     
  17.     public static void main(String[] args) {      
  18.         System.out.println(todo());      
  19.      
  20.     }      
  21. }     

此时,运行结果依旧是
in catch
in final
1

但是通过单步执行,会发现,两种代码的执行顺序有少许差别

第一种代码的try/catch单步执行顺序为
7->10->8

第二种代码的try/catch单步执行顺序为
7->8->10->8

这里我们对其进行了研究,从中间码入手,首先来分别看看两者的中间码:

上述第一块代码的中间码
  1. 11  ldc <String "in catch"> [22]   
  2. 13  invokevirtual java.io.PrintStream.println(java.lang.String) : void [24]   
  3. 16  getstatic java.lang.System.out : java.io.PrintStream [16]   
  4. 19  ldc <String "in final"> [30]   
  5. 21  invokevirtual java.io.PrintStream.println(java.lang.String) : void [24]   
  6. 24  iconst_1   
  7. 25  ireturn  

可以发现,明显的执行顺序,1行把装入字符串转入内存,2行打印,4行在把字符串装入内存,5行再打印,7行返回

上述第二块代码的中间码
  1. 13  ldc <String "in catch"> [22]   
  2. 15  invokevirtual java.io.PrintStream.println(java.lang.String) : void [24]   
  3. 18  iload_0 [b]   
  4. 19  istore_3   
  5. 20  getstatic java.lang.System.out : java.io.PrintStream [16]   
  6. 23  ldc <String "in final"> [30]   
  7. 25  invokevirtual java.io.PrintStream.println(java.lang.String) : void [24]   
  8. 28  iload_3
  9. 29  ireturn  

 

以上的过程,分析下中间码,还是可以理解的,但是非常非常让人奇怪的是,如下的代码(请还是注意不同的细节)

java 代码
  1. public class Test {         
  2.     private static int todo() {         
  3.         int b=1;         
  4.         try{         
  5.             int a=2/0;         
  6.         } catch(Exception e) {         
  7.             System.out.println("in catch");      
  8.             return b;         
  9.         } finally {  
  10.             b=3;       
  11.             System.out.println("in final");         
  12.         }         
  13.         return 2;         
  14.     }         
  15.     /**      
  16.      * @param args      
  17.      */        
  18.     public static void main(String[] args) {         
  19.         System.out.println(todo());         
  20.         
  21.     }         
  22. }        

此时运行结果照样是
in catch
in final
1

单步执行结果是 7->8->10->11->8
想不通的是,根据单步执行,在finally里对b进行了修改,但是,返回的仍旧是1

再来看看这个代码的中间码:

第三个代码的中间码
  1. 13  ldc <String "in catch"> [22]   
  2. 15  invokevirtual java.io.PrintStream.println(java.lang.String) : void [24]   
  3. 18  iload_0 [b]   
  4. 19  istore_3   
  5. 20  iconst_3   
  6. 21  istore_0 [b]   
  7. 22  getstatic java.lang.System.out : java.io.PrintStream [16]   
  8. 25  ldc <String "in final"> [30]   
  9. 27  invokevirtual java.io.PrintStream.println(java.lang.String) : void [24]   
  10. 30  iload_3   
  11. 31  ireturn  

因为,其实我没怎么学过汇编,只是初步的分析了
3行加载b的地址,4行在地址3储存b的值(此时地址3的值为1),5行加载一个常量,6行把常量存入b的地址(此时b的值为3),10行加载地址3的值,最后返回值。
不知道这样的解释是否合理,也请,希望能够得到一个对于try./catch块执行问题的通俗答案,谢谢!

分享到:
评论
1 楼 Qieqie 2007-08-31  
参考某New版某贴:《在finally赋值为什么无效》
http://www.iteye.com/topic/79092

然后本贴可以结贴了。

相关推荐

    java基础知识-try-catch的使用

    try块中包含可能会产生异常的代码,当try块内的代码发生异常时,程序会立即跳转到与异常类型相匹配的catch块进行处理。 在catch块中,你可以编写适当的处理逻辑来处理特定类型的异常。每个catch块可以捕获不同类型...

    关于Java中的try-catch-finally语句和return

    第一:return语句并不是函数的终出口,如果有finally语句,这在return之后还会执行finally(return的值会暂存在栈里面,等待finally执行后再返回)  第二:finally里面不建议放return语句,根据需要,return语句...

    Java中的异常处理机制.md

    try-catch-finally语句是Java中处理异常的主要方式。try块包含可能会抛出异常的代码,catch块包含用于处理特定类型异常的代码,finally块包含无论是否发生异常都需要执行的代码。 示例: ```java try { // 尝试...

    try-catch-finally执行顺序验证

    try-catch-finally执行顺序验证(左边是.java文件,右边是.class文件) 提示: try、catch块内的return操作编译后会变成把return的值保存到变量var的操作。 总结: try、catch块内的return操作编译后会变成把return的值...

    Jungle68#-#[Java] try catch finally,try里有return,finally还执行么?1

    Condition 3: try中有异常,try-catch-finally里都没有return ,finally 之后有个returntry中有异常以后,根据

    谈谈Java中try-catch-finally中的return语句

    我们知道return语句用在某一个方法中,一是用于返回函数的执行结果,二是用于返回值为void类型的函数中,仅仅是一个return语句(return ;),此时用于结束方法的执行,也即此return后的语句将不会被执行,当然,这种...

    java 面试常见问题整理

    finally 中的代码一定会执行吗? 如何使用 try-with-resources 代替try-catch-finally? I/O 什么是序列化?什么是反序列化? Java 序列化中如果有些字段不想进行序列化,怎么办? 获取用键盘输入常用的两种方法 Java ...

    java大厂面经、直击BAT

    finally 一定会被执行,如果 finally 里有 return 语句,则覆盖 try/catch 里的 return , 比较爱考的是 finally 里没有 return 语句,这时虽然 finally 里对 return 的值进行了修改,但 return 的值并不改变这种...

    惠普测试基础Java考核答案

    1、说明try/catch/finally语句块的作用?...从try程序块中得到异常,然后再catch块中做处理(一般是抛出,数据回滚,写日志等等),在finally块中的程序是最后执行的(不论是否前面的程序抛出异常)。

    try:Java 8 的 Try monad

    对于单调执行可能会失败的任务的单例组合,而不必使用一系列嵌套的try / catch语句,try尤其有用。 您可以通过形成一个尝试attempt()或attemptApply() Try&lt; String&gt; value = Try . attempt(() - &gt; keyValueStore ....

    Java面试问题带答案40道.docx

    1. Java中有哪些数据类型? 答:Java中有八种基本数据类型,分别为byte、...Java中使用try-catch语句来捕获异常并进行处理。 7. 什么是Java中的泛型? 答:泛型是Java中一种参数化类型的概念,允许在编译时期检查类

    快速学习-Scala异常

    catch块用于处理try块中发生的异常。可以根据需要在程序中有任意数量的try…catch块。 语法处理上和Java类似,但是又不尽相同 Java异常处理回顾 try { // 可疑代码 int i = 0; int b = 10; int c = b / i; // ...

    Java期末考试真题试卷及复习资料【高级编程】

    Java期末考试真题试卷及复习资料【高级编程】 Java高级编程期末考试真题试卷及复习资料 名词解释 泛型 答即参数化类型允许程序创建集合时指定集合元素的类型在定义方法类接口时使用类型形参类型形参将在声明变量调用...

    Java学习笔记

    finally中的代码和try-catch中的代码冲突时,finally中的代码一定会被执行且会忽略try-catch中的代码。但是如果try-catch中有System.exit(0);(虚拟机退出语句),则不会去执行fianlly中的代码。

    10道Java常见异常面试题含答案(很全)

    在Java中,异常(Exception)是一种特殊的对象,表示程序运行过程中出现的问题。Java提供了很多内置的异常类,例如NullPointerException、IndexOutOfBoundsException等。此外,程序员也可以创建自定义的异常类。 ...

    实验五 Java异常处理实验.docx

    实验五 Java异常处理实验.docx

    简单谈谈java的异常处理(Try Catch Finally)

    在程序设计中,进行异常处理是非常关键和重要的一部分。一个程序的异常处理框架的好坏直接影响到整个项目的代码质量以及后期维护成本和难度。

    josonle#Coding-Now#finally语句如何执行1

    - 无论try是否发生异常,finally语句都会执行- 如果try/catch中包含控制转移语句(return、continue、break),finally

    Java精华(免费版)

     在main()方法中,如果要调用method1(),你必须把这个调用放在try/catch程序块当中,因为它会抛出Checked exception。   相比之下,当你调用method2()时,则不需要把它放在try/catch程序块当中,因为它会抛出的...

    什么是Java中的异常处理机制?Java中的异常分为哪些类型?(java面试题附答案).txt

    Java中的异常处理机制是一种用于捕获和处理程序运行过程中可能出现的异常情况的机制。...处理方式可以是使用 try-catch 块捕获异常并处理,或者在方法签名中使用 throws 关键字声明将异常抛出给调用者处理。

Global site tag (gtag.js) - Google Analytics