我总是假设每次用Java调用方法时,方法都会再次执行。我假设返回值不会自动存储,除非我将其存储在变量中。
然后我在Princeton's algs4.BST class中遇到了这个代码,他们在那里分别调用了三个方法:
private boolean check() {
if (!isBST()) StdOut.println("Not in symmetric order");
if (!isSizeConsistent()) StdOut.println("Subtree counts not consistent");
if (!isRankConsistent()) StdOut.println("Ranks not consistent");
return isBST() && isSizeConsistent() && isRankConsistent();
}
他们根本不关心表现吗?或者编译器是否足够智能保留每个方法的第一个返回值以在return语句中使用?
很抱歉,如果这是一个副本,似乎这个答案应该存在,但我在这里或在Java文档中找不到它。我找到了这些(和其他人),但他们没有回答我的问题:
Is this the cleanest way to repeat method call in Java?
How to call a method without repeat from other methods in java
答案 0 :(得分:1)
Java语言规范明确无条件地声明对方法调用表达式的评估涉及执行指定方法的代码。 JLS 8就是这样说的:
在运行时,方法调用需要五个步骤。首先是目标 可以计算参考。其次,参数表达式是 评估。第三,要调用的方法的可访问性是 检查。第四,要执行的方法的实际代码是 位于。第五,创建一个新的激活帧,同步是 必要时执行,控制转移到方法代码。
(JLS 8, 15.12.4;重点补充)
因此,无论是否可以预期计算相同的值,第二次调用方法都会产生第二次成本。可以想象,JIT编译可以优化它,但是有更多的考虑因素,而不是相同的结果是否将被计算,并且你不可能看到任何JIT动作仅由给定方法的两次调用触发。
底线:是的,代码的作者根本不关心性能。他们可能认为所呈现的实现比避免冗余方法调用的实现更清晰,或者他们可能有其他个人原因进行选择。这种对实用性的漠视在用于学术目的的代码中并不少见,例如提供的代码。
答案 1 :(得分:1)
该代码中的check
函数仅在上下文中调用:
assert check();
在生产代码中通常不启用断言,如果未启用断言,则assert
语句绝对不会执行任何操作。所以check
函数只会在调试运行中运行。这一事实并不能使许可证具有任意低效率,但通常不会尝试优化此类代码。作为断言运行的代码点在显示不变量,前提条件或后置条件时是明显无误的,并且优化 - 即使是将结果保存在局部变量中的微不足道 - 也无助于实现该目标。 / p>
断言是包含布尔表达式的断言语句。断言被启用或禁用。如果启用了断言,则断言的执行会导致对布尔表达式进行求值,如果表达式求值为false,则会报告错误。如果断言被禁用,则断言的执行不会产生任何影响。