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

在方法调用和参数传入的情况下,是否保证Java评估顺序

夏侯昆琦
2023-03-14
问题内容

我做了一些有关JLS
15.7.4和15.12.4.2的阅读,但不能保证不会有任何
编译器/运行时优化改变 方法参数求值的顺序。

假设以下代码:

public static void main (String[] args) {
  MyObject obj = new MyObject();
  methodRelyingOnEvalOrder(obj, obj.myMethod());
}

public static Object methodRelyingOnEvalOrder(MyObject obj, Object input) {
  if (obj.myBoolean())
    return null;
  else
    return input;
}

是否保证编译器或运行时 不会 进行如下错误的优化?这种优化看似正确,但当评估顺序很重要时,它是错误的。

在调用obj.myMethod更改将由返回的值的情况下,obj.myBoolean至关重要的是obj.myMethod首先调用,因为methodRelyingOnEvalOrder要求此更改首先发生。

//*******************************
//Unwanted optimization possible:
//*******************************
public static void main (String[] args) {
  MyObject obj = new MyObject();
  methodRelyingOnEvalOrder(obj);
}

public static Object methodRelyingOnEvalOrder(MyObject obj) {
  if (obj.myBoolean())
    return null;
  else
    return obj.myMethod();
}
//*******************************

如果可能, 请显示一些支持您答案的资源或Java文档。

注意:
请不要要求重写代码。这是我质疑评估顺序保证和编译器/运行时优化保证的特定情况。的执行obj.myMethod必须在发生main的方法。


问题答案:

您引用的JLS(15.7.4)的位 确实 保证:

每个参数表达式似乎都在其右侧任何参数表达式的任何部分之前被完全评估。

并且在15.12.4.2中:

然后,使用参数值继续评估,如下所述。

“出现于”部分允许进行一些优化,但是它必须不 可见 “评估然后继续” 之前
评估所有参数的事实表明,在执行该方法之前,这些参数实际上已被完全评估。(或者至少是可见的结果。)

因此,例如,如果您有以下代码:

int x = 10;
foo(x + 5, x + 20);

可能 进行优化以同时评估x + 5和评估x + 20:您无法检测到这种情况。

但是,在您给出的情况下,您 能够检测到对调用obj.myMethod之后发生的调用obj.myBoolean(),因此这 根本不是
有效的优化。

简而言之:您可以假定一切都将以明显的方式执行。



 类似资料:
  • 问题内容: 可以安全地假设函数参数在Python中是从左到右求值的吗? 参考文献指出,这种情况会发生,但是也许有某种方法可以更改此顺序,这可能会破坏我的代码。 我想做的是为函数调用添加时间戳: 我知道我可以按顺序评估参数: 但是它看起来不太优雅,因此如果可以依靠它,我宁愿采用第一种方法。 问题答案: 是的,Python始终从左到右评估函数参数。 据我所知,这适用于任何逗号分隔的列表:

  • 问题内容: 以下内容在Python 3.6中从不打印任何内容 相反,它只是坐在那里烧坏了CPU。问题似乎在于,如果迭代器位于无限空间内,则永远不会返回迭代器,因为它首先评估完整的迭代器。鉴于假设应该是发电机,这令人惊讶。 我本来希望这会开始计数(到无穷大),就像这个生成器的行为(直接从docs取得): 但是,尽管我的生成器立即开始计数,但使用的生成器根本不计数。 其他工具可以达到我的期望。例如,以

  • 这是一个使用合并排序的程序,从1到1000对1000个数字的列表进行排序。它显示原始列表,然后调用递归方法对其进行排序,然后显示。 代码中我不明白的是这两行: 合并排序(数字,低,中);//在方法中,它会说“这里” 合并排序(数字,中间1,高); 我是java的初学者,这与我所学的一切背道而驰,因为我无法理解如何在方法中调用方法。除非它是一个我怀疑的对象。有人能解释一下这两行代码的作用吗?

  • 问题内容: 我知道Java在这种情况下具有智能/惰性评估: 但是关于: 即使返回true 也被调用? 问题答案: 在Java(和其他类似C的语言)中,这称为 短路评估 。* 是的,在第二个示例中总是被调用。也就是说,除非编译器/ JVM可以确定它没有可观察到的副作用,否则在这种情况下它可以选择进行优化,但是无论如何您都不会注意到它们之间的差异。 两者截然不同; 前者本质上是一种优化技术,而第二种则

  • 问题内容: 我正在阅读一些Java文本,并获得以下代码: 在本文中,作者没有给出明确的解释,最后一行的效果是: ; 我不确定自己是否理解:评估是如何发生的? 问题答案: 让我说得很清楚,因为人们一直误会这一点: 子表达式的求值顺序与关联性和优先级无关。结合性和优先级确定以什么顺序运营商执行,但不以什么顺序确定的子表达式进行评估。你的问题与子表达式的计算顺序有关。 考虑一下。乘法比加法具有更高的优先

  • 问题内容: 为什么这些示例中的第一个不起作用,而其他所有示例都起作用? 问题答案: 这既不是范围问题,也不是关闭问题。问题在于 声明 和 表达式 之间的理解。 JavaScript代码(即使是Netscape的第一个JavaScript版本和Microsoft的第一个副本)也要分两个阶段处理: 阶段1:编译-在此阶段,代码被编译成语法树(字节码或二进制取决于引擎)。 阶段2:执行-然后解析解析的代