向方法传递参数时 Java 是惰性的吗?

Is Java lazy when passing parameters to a method?

我正在使用此代码:

A a = aMap.contains(key) ? aMap.get(key) : createAExpensively(key);

我相信 Java 是惰性的,所以如果 aMap.contains(key)) 那么永远不会调用 createAExpensively() 函数。

然后,我偶然发现了 Map.getOrDefault() 方法。如果我们改用:

A a = aMap.getOrDefault(key, createAExpensively(key));

Java还在偷懒调用createAExpensively()函数吗?

根据this question,似乎Java会先创建对象A并将其作为方法参数传递,但我不太确定。

如果Java在使用Map.getOrDefault()时不偷懒,那这个方法有什么意义?

Java一点也不懒惰。您正在使用条件运算符来检查是否 aMap.contains(key)。如果这是真的,它永远不会调用 createAExpensively(key)aMap.get(key)

在那种情况下它并不懒惰。

该方法的要点是,很多时候默认值是一个常量或您已经计算过的值。例如,当您获得某种计数时,您可能会使用 getOrDefault(key, 0),而缺少的键应计为零。

Is Java still lazy in calling the createAExpensively() function? [in .getOrDefault(key, createAExpensively(key))]

在实际调用函数之前评估函数参数(从左到右)。所以 createAExpensively(key) 将在调用 getOrDefault 之前被评估。此行为也称为 applicative order evaluation strategy.

If Java is not lazy when using Map.getOrDefault(), what is the point of that method?

当默认值的创建成本不高时很有用, 例如,当它是一个已经计算出的值或常量时。 在这种情况下,Map.getOrDefault(...) 调用允许使用比三元运算符更紧凑的语法。

如果默认值的计算成本很高, 如果您真的想将计算值放入地图, 然后从 Java 8 开始, 你可以使用 computeIfAbsent:

A a = aMap.computeIfAbsent(key, k -> createAExpensively(k));

这称为 "short-circuit evaluation" 而不是惰性求值:JVM 不是 延迟 createExpensively() 的求值,而是 避免 完全没有必要,即如果条件成立。

另请参阅 Whosebug 上以下问题的答案:

Java logical operator short-circuiting

一点都不懒惰。

此代码

A a = aMap.contains(key) ? aMap.get(key) : createAExpensively(key);

评估为

if (aMap.contains(key)) 
{
  a = aMap.get(key);
}
else 
{
  a = createAExpensively(key);
}