JAVA finally字句的异常丢失和返回值覆盖解析

转载:http://blog.csdn.net/sureyonder/article/details/5560538

Java虚拟机在每个try语句块和与其相关的catch子句的结尾 处都会“调用”finally子句的子例程。实际上,finally子句在方法内部的表现很象“微型子例程”。finally子句正常结束后-指的是finally子句中最后一条语句正常执行完毕,不包括抛出异常,或执行return、continue、break等情况,隶属于这个finally子句的微型子例程执行“返回”操作。程序在第一次调用微型子例程的地方继续执行后面的语句。

finally“微型子例程”不等同于方法函数的调用,finally子句都是在同一个栈内执行的,微型子例程的“返回”操作也不会涉及到方法退栈,仅仅是使程序计数器pc跳转到同一个方法的一个不同的位置继续执行。

一 异常丢失

[java] view plaincopy

  1. public static void exceptionLost()
  2. {
  3. try
  4. {
  5. try
  6. {
  7. throw new Exception( "exception in try" );
  8. }
  9. finally
  10. {
  11. throw new Exception( "exception in finally" );
  12. }
  13. }
  14. catch( Exception e )
  15. {
  16. System.out.println( e );
  17. }
  18. }

exceptionLost()的输出结果是“exception in finally”,而不是try块中抛出的异常,这是JAVA异常机制的一个瑕疵-异常丢失。

在字节码中,throw语句不是原子性操作。在较老的JDK中,exceptionLost()中try块的throw语句分解为几步操作:

1) 把Exception("exception in try")对象引用存储到一个局部变量中
  astore_2  // pop the reference to the thrown exception, store into local variable 2
2) 调用finally微型子程序
3) 把局部变量中的Exception("exception in try")对象引用push到操作数栈顶,然后抛出异常
  aload_2  // push the reference to the thrown exception from local variable 2

  athrow   // throw the exception

如果finally通过break、return、continue,或者抛出异常而退出,那么上面的第3步就不会执行。

在JDK1.6中,通过字节码我们可以看到,finally子句作为一种特殊的catch来实现的,下面是exceptionLost()方法的异常表:

Exception table:
  from   to   target  type
   0     10    10     any
 0     21    21     Class java/lang/Exception

finally可以捕获从0行到9行之间抛出的任何类型(any)的异常,并重新抛出捕获的异常,或者抛出一个自己构造的新异常,这个新异常就会覆盖try语句块中的异常。

二 返回值覆盖

[java] view plaincopy

  1. public static int getValue()
  2. {
  3. int value = 0;
  4. try
  5. {
  6. value = 100;
  7. return value;
  8. }
  9. finally
  10. {
  11. value = 200;
  12. }
  13. }

这个方法的返回值是100还是200?结果是100。
在字节码中,return语句不是原子性操作,它会把getValue()中的return语句分解为几步操作:
1) 把value值存储到一个局部变量(这里命名为temp)中:
   iload_0   // push local variable 0 - the 100
   istore_2   //  pop an int (the 100), store into local varaible 2
2) 调用finally微型子程序
3) 把局部变量(指temp)的值push到操作数栈顶,然后返回到调用方法
     iload_2  // push local varaible 2 - the 100
   ireturn      // return int on top of the stack - the 100: return 100

由于return语句在返回之前会把返回值保存到一个临时的局部变量中,所以在finally子句内对value重新赋值不会影响返回值。

了解finally子句内在的一些知识,我们能够了解finally能够做什么和不能够做什么,这样会帮助我们正确使用finally子句。

时间: 2024-10-07 22:02:41

JAVA finally字句的异常丢失和返回值覆盖解析的相关文章

java多线程之从任务中获取返回值

package wzh.test; import java.util.ArrayList; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; class TaskWithResult implements Callable<Strin

Java异常时的返回值

先来看一个小程序: public class JavaException {          public static void main(String[] args)          {                    System.out.println(test());          }          public static int test()          {                    int i=0;                    tr

059、Java中定义一个有参数无返回值的方法

01.代码如下: package TIANPAN; /** * 此处为文档注释 * * @author 田攀 微信382477247 */ public class TestDemo { public static void main(String[] args) { pay(10.0); // 调用方法 pay(-10.0); // 调用方法 } public static void pay(double money) { // 购买支付操作 if (money > 0.0) { // 现在已

接口API测试和返回值JSON解析的插件

火狐插件1.   HttpRequest作用:接口API测试例子:http://192.168.10.61:8080/ZHCS/user/loginApp.do?phone=admin&pwd=admin接口以?作为结束, 连接用& 2.   JSON-handle作用:对json进行解析

Java中的常客异常(一)

Java的基本理念是"结构不佳的代码不能运行"!!!!! 大成若缺,其用不弊. 大盈若冲,其用不穷. 在这个世界不可能存在完美的东西,不管完美的思维有多么缜密,细心,我们都不可能考虑所有的因素,这就是所谓的智者千虑必有一失.同样的道理,计算机的世界也是不完美的,异常情况随时都会发生,我们所需要做的就是避免那些能够避免的异常,处理那些不能避免的异常.这里我将记录如何利用异常还程序一个"完美世界". 一.为什么要使用异常 首先我们可以明确一点就是异常的处理机制可以确保我

Java基础---Java中无参数带返回值方法的使用(三十七)

Java 中无参带返回值方法的使用 如果方法不包含参数,但有返回值,我们称为无参带返回值的方法. 例如:下面的代码,定义了一个方法名为 calSum ,无参数,但返回值为 int 类型的方法,执行的操作为计算两数之和,并返回结果 在 calSum( ) 方法中,返回值类型为 int 类型,因此在方法体中必须使用 return 返回一个整数值. 调用带返回值的方法时需要注意,由于方法执行后会返回一个结果,因此在调用带返回值方法时一般都会接收其返回值并进行处理.如: 运行结果: 不容忽视的"小陷阱&

ActionResult的其它返回值

我们上边所看到的Action都是return View();我们可以看作这个返回值用于解析一个aspx文件.而它的返回类型是ActionResult如 public ActionResult Index() { return View(); } 除了View()之外那我们这里还能用于返回什么值呢? 一.ascx页面 场景:要返回代码片断,比如Ajax返回一个子页 我们先新建一个Action public ActionResult Ascx() { return PartialView(); }

Java异常-可能会出现异常丢失的情况&amp;finally

finally的两种特性: 对于没有垃圾回收和析构函数自动调用机制的语言来说,Java中的finally非常重要.它能使程序员保证: 1.无论异常是否被抛出,finally子句总能被执行.这个特性我们可以用来解决以下问题:Java的异常不允许我们回到异常抛出的地点时,该如何应对?把try块放在循环里,建立了一个"程序继续执行之前必须要达到"的条件.还可以加入一个static类型的计数器之类的装置,使循环在放弃之前能尝试一定的次数,这将使程序的健壮性更上一个台阶. 2.无论try块发生了

java异常丢失及异常链

异常丢失的情况: 先定义三个异常: public class ExceptionA extends Exception { public ExceptionA(String str) { super(); } } public class ExceptionB extends ExceptionA { public ExceptionB(String str) { super(str); } } public class ExceptionC extends ExceptionA { publi