在下面的例子中,我是否需要担心性能,并保存昂贵调用的结果,还是编译器意识到它可以执行一次昂贵的调用?Java编译器优化
String name;
if (object.expensiveCall() != null) {
name = object.expensiveCall().getName();
}
在下面的例子中,我是否需要担心性能,并保存昂贵调用的结果,还是编译器意识到它可以执行一次昂贵的调用?Java编译器优化
String name;
if (object.expensiveCall() != null) {
name = object.expensiveCall().getName();
}
编译器不会(通常)只进行一次调用,因为它可能有副作用,或者结果可能不稳定 - 它不可能知道什么时候你想让它忽略第二个调用,并且当它实际上需要它时再次拨打电话。您需要保存结果:
final ExpensiveCallResult nullableResult = object.expensiveCall();
String name;
if (nullableResult != null) {
name = nullableResult.getName();
}
Java编译器怎么知道,expensiveCall
没有副作用?在一般情况下 - 它不能。另外:您可以随时重新编译object
的类,而无需重新编译当前的类。如果expensiveCall
有副作用现在会发生什么?没有办法自动优化。
顺便说一句:JIT编译器在运行时可能有更多的信息。但昂贵的调用通常不考虑内联,因此也没有进一步的优化步骤。
不,你将需要重写它只能拨打电话一次:
String name;
MyResult result = object.expensiveCall();
if (result != null) {
name = result.getName();
}
您也可以缩短语法来进行分配,并在同一行检查:
String name;
MyResult result;
if ((result = object.expensiveCall()) != null) {
name = result.getName();
}
您正在寻找名为memoization的物品。 This question表明Java本身不能做到这一点。
一般而言,只有在编译器/ JIT可以证明该函数没有副作用时才可以进行记忆。所以我不会指望它。
但是真的很难保存结果吗?
String name;
ObjectType temp = object.expensiveCall();
if (temp != null) {
name = temp.getName();
}
在将来你可以编译和反编译类回来JAD看看编译器优化。
在你的情况下,它不会优化任何东西。
如果结果从数据库或数据库获取数据,则数据会发生变化。所以逻辑上它不会被保存。 – user717572 2012-02-27 17:45:55
它将简化可以内联的简单案例的代码,并且JVM(不是javac编译器)可以检测到没有副作用。 – 2012-02-27 18:05:48