当前位置: 首页 > 面试题库 >

从finally块返回时Java的奇怪行为

杨乐意
2023-03-14
问题内容

尝试这段代码。为什么getValueB()返回1而不是2?毕竟,递增两次被调用两次。

    public class ReturningFromFinally
    {
      public static int getValueA() // This returns 2 as expected
      {
         try     { return 1; }
         finally { return 2; }
      }

      public static int getValueB() // I expect this to return 2, but it returns 1
      {
        try     { return increment(); }
        finally { increment(); }
      }

      static int counter = 0;

      static int increment()
       {
          counter ++;
          return counter;
       }

      public static void main(String[] args)
      {
          System.out.println(getValueA()); // prints 2 as expected
          System.out.println(getValueB()); // why does it print 1?
      }
}

问题答案:

毕竟,递增两次被调用两次。

是的,但是返回值是 第二次调用 之前 确定的。

返回的值由该 时间点在 return语句中的表达式求值确定,而不是“仅在执行离开方法之前”。

从JLS的14.17节开始:

一个带有Expression的return语句试图将控制权转移到包含它的方法的调用者;Expression的值成为方法调用的值。更准确地说,
执行这种return语句首先会评估Expression
。如果对表达式的求值由于某种原因而突然完成,则return语句由于该原因而突然完成。如果对表达式的求值正常完成,产生一个值V,则return语句突然完成,原因是返回值为V的返回值。

然后
根据JLS的14.20.2节,将
执行转移到该finally块。但是,这不会重新评估return语句中的表达式。

如果您的finally块是:

finally { return increment(); }

那么新的返回值将是该方法的最终结果(根据14.20.2节)-但您并未这样做。



 类似资料:
  • 问题内容: 近我很惊讶地发现,在Java的finally块中可能有一个return语句。 似乎很多人都认为这是一件坏事,如“ 不要在finally子句中返回”中所述。更深入地研究,我还发现“ Java的回报并不总是 ”,这在finally块中显示了其他类型的流控制的一些非常可怕的示例。 因此,我的问题是,谁能给我一个示例,其中finally块中的return语句(或其他流控制)产生更好/更具可读性

  • 但是,当从handleAsyncErrors()流链接ObjectNode并到达相同的httpCallbackFlow()时,我们会得到一个异常,该异常由 restClientException:无法写入请求:在org.springframework.web.client.restTemplate$HttpEntityRequestCallback.dowithRequest(restTempla

  • 我的程序读取一个自定义生成的字符串,它遵循以下模式: #INT{0,1,2}/STRING/LONG#INT{0,1,2}/STRING/LONG## 这是字符串开头和结尾的一个散列,分隔每个子字符串,每个子字符串包含0-2的int、字符串名称和长值(取自系统时钟)。这些子值由前斜杠分隔。 我的程序成功地在函数“splitOnHash”的散列上拆分了主字符串,并将其分配给一个字符串数组列表,我可以

  • 我有以下代码: 假设我现在将电脑的时区设置为太平洋时间(PDT为UTC-7),则打印 2012年6月29日星期五08:15:00太平洋标准时间 PDT不是比IST(印度标准时间)晚12.5小时吗?这个问题在任何其他时区都不会发生-我尝试了UTC、PKT、MMT等,而不是日期字符串中的IST。Java中有两个IST吗? 注意:实际代码中的日期字符串来自外部源,因此我不能使用GMT偏移量或任何其他时区

  • 问题内容: 有没有人看到像这样的方法签名后放置的数组? 版画 过去,“ C”兼容性是一种奇怪的表示法,但我也无法想象有人用C编写这种代码。 有谁知道为什么甚至允许这样做? 如果有问题,我正在使用Java 7 update 10。 这与Java 6中的功能相同。http://ideone.com/91rZV1 顺便说一句,这不会编译,我也不希望它编译 问题答案: 有谁知道为什么甚至允许这样做? 在这