在下面的例子中,我是否需要擔心性能,並保存昂貴調用的結果,還是編譯器意識到它可以執行一次昂貴的調用?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