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

即使分配是try中的最后一个操作,也可以在catch中重新分配最终变量吗?

赖浩荡
2023-03-14
问题内容

我很相信这里

final int i;
try { i = calculateIndex(); }
catch (Exception e) { i = 1; }

i如果控制到达捕获块,则不可能已经分配。但是,Java编译器不同意并主张the final local variable i may already have been assigned

我在这里仍然缺少一些微妙之处,还是这仅仅是Java语言规范用来识别潜在重新分配的模型的弱点?我主要担心的是Thread.stop(),可能会导致异常抛出“异常”,但是我仍然看不到分配后如何抛出异常,这显然是try块中的最后一个动作。

如果允许,上述成语会使我的许多方法变得更简单。请注意,该用例在诸如Scala之类的语言中具有一流的支持,这些语言始终采用 Maybe monad:

final int i = calculateIndex().getOrElse(1);

我认为这种使用情况作为一个相当不错的动力,让其中的一个特殊情况 i绝对未分配 的捕捉块内。

更新

经过一番思考,我甚至可以确定这只是JLS模型的弱点:如果我声明公理“在所示示例中,i当控制权到达catch-
block时绝对未分配”,它将不会与任何其他公理冲突或定理。在将i其分配给catch块之前,编译器将不允许对其进行任何读取,因此i无法观察是否分配了该事实。


问题答案:

这是对最有力论点的总结,以支持这样的论点:当前的定值分配规则必须在不破坏一致性的前提下放宽(A),然后再提出我的反驳(B):

  • :在字节码级别,对变量的写入不是try块中的最后一条指令:例如,最后一条指令通常是goto对异常处理代码的跳转;

  • :但是,如果规则状态i绝对未分配 的捕捉块内,它的值可以不被观察到。不可观察的价值与没有价值一样好。

  • :即使编译器声明i绝对未分配 ,调试工具仍然可以看到该值;

  • B :实际上,调试工具始终可以访问未初始化的局部变量,该变量在典型的实现中将具有任意值。未初始化的变量和在实际写入发生后突然完成初始化的变量之间没有本质区别。不管此处考虑的特殊情况如何,该工具都必须始终使用其他元数据来为每个局部变量知道 明确分配 该变量的指令范围,并且仅允许在执行发现自身处于该范围内时观察其值。

定论:

该规范可以持续接收更多细粒度的规则,这些规则可以使我发布的示例得以编译。



 类似资料:
  • 我很确信在这里 如果控制到达捕获块,不可能已经被分配了。但是,Java编译器不同意并声称。 我在这里是否仍然缺少一些微妙之处,或者这只是Java语言规范用于识别潜在重新分配的模型的弱点?我主要担心的是像这样的东西,这可能会导致异常被“凭空”抛出,但我仍然不明白如何在分配后抛出它,这显然是尝试块中的最后一个操作。 如果允许的话,上面的习惯用法会使我的许多方法变得更简单。注意,这个用例在语言中有一流的

  • 因为我相信这是一个很好的编程实践,所以如果我的所有(局部或实例)变量只需要编写一次,我就将它们设为< code>final。 但是,我注意到当变量赋值可以抛出异常时,您不能将所述变量设为最终变量: 有没有办法在不诉诸临时变量的情况下做到这一点?(或者这不是最终修饰符的正确位置?)

  • 问题内容: 我有一个座位数组,该数组有两个字符串(已选择和为空)。单击鼠标后,我想遍历数组并找到选定的座位。当我按下按钮时,它说: 无法分配最终的局部变量seatno,因为它是用封闭类型定义的。 问题答案: 关键是封闭类型中的方法局部变量实际上已 复制 到匿名类的实例中(这是由于激活框架的问题,但我将不做进一步的详细介绍,因为这与问题无关)。这就是为什么它们需要是final的原因,因为嵌套类型实例

  • 问题内容: 任何人都可以告诉我在Java上下文中以下行的含义是什么: 除非变量是不可变的,否则仍然可以对其进行操作 据我所知,通过将任何变量声明为final,就无法再次对其进行更改,那么上一行中 不可变 一词的含义是什么? 问题答案: 这意味着,如果您的最终变量是引用类型(即不是像int这样的基元),则只有引用是不能更改的。不能使它引用不同的对象,但是如果类允许,它所引用的对象的字段仍可以更改。例

  • 本文向大家介绍try-catch-finally 中哪个部分可以省略?相关面试题,主要包含被问及try-catch-finally 中哪个部分可以省略?时的应答技巧和注意事项,需要的朋友参考一下 try-catch-finally 其中 catch 和 finally 都可以被省略,但是不能同时省略,也就是说有 try 的时候,必须后面跟一个 catch 或者 finally。

  • 本文向大家介绍我们可以在Java中的另一个try catch块中声明一个try catch块吗?,包括了我们可以在Java中的另一个try catch块中声明一个try catch块吗?的使用技巧和注意事项,需要的朋友参考一下 是的,我们可以 在另一个try-catch块中声明一个try-catch块,这称为嵌套try-catch块。 嵌套的尝试捕获块 如果一个内部的try statemen牛逼没