2017-09-14 17 views
4

我正在閱讀Java中的參數化日誌記錄,因爲它執行延遲評估,所以它使用參數化日誌記錄而不是串聯。無法理解爲什麼要使用參數化日誌記錄

所以不是

logger.debug("My text is" + x); 

使用:

logger.debug("My text is {}", x); 

如果跟蹤級別設置爲只有信息的日誌,爲什麼拼接發生在第一個場景?

另外,如果我有一個耗時的日誌功能,據說使用:

logger.debug("My text is {}",() -> compute()); 

,而不是

logger.debug("My text is {}", compute()); 

在這種情況下,爲什麼被認爲是一個更好的辦法拉姆達方法。在字符串連接的情況下不會計算也會被稱爲懶惰嗎?

回答

9

在輸入logger.debug()之前,必須計算參數。

在第一種情況下,您在將結果字符串傳遞給方法(可能不會使用它)之前總是獲得字符串連接。使用參數化版本不需要連接,x被傳入並且可以使用或不使用。

compute()相同。在輸入方法之前,非lambda版本將始終執行compute(),因爲它將需要compute()的結果以調用該方法。

拉姆達版本將通過方法(實際上它運行時被請求的結果的方法的Supplier)作爲參數,而不是方法結果,並且如果需要的話它只會被執行。

+0

感謝您的詳細解釋。這是否意味着在調用任何函數之前,先評估所有參數,然後函數被稱爲 – user1692342

+2

@ user1692342,如果需要一些參數,則爲yes –

+3

@ user1692342正確。 lambda方法只允許將參數作爲運行'compute()'的'Supplier'來評估。因此它被完全評估,但實際的compute()方法尚未運行。 – Kayaman

5

這個想法很簡單。通常情況下,應用程序使用記錄器的頻率非常高,但記錄本身就是耗費資源的操作,至少因爲需要將某些內容寫入硬盤驅動器。看你的例子:

logger.debug("My text is " + x); 

讓我們假設記錄器配置中打開INFO級別。然後代碼執行這一行,它需要評估參數在debug函數中傳遞,所以它的確如此。但在debug裏面,記錄器將檢查打開哪個日誌級別,它將是INFO。在這種情況下,所需的消息不應該被記錄下來,因此組裝參數字符串所需的計算將被視爲浪費時間。 爲了克服這些問題,你可以檢查日誌級別調用方法之前打開,這樣

if (logger.isDebugEnabled()) { 
    logger.debug("My text is " + x) 
} 

它會更好,因爲你將裝配消息只是它的需要,但這裏的問題是,logger.isDebugEnabled()兩次評估。首先在你的代碼裏面,然後在logger.debug()之內。 這就是參數化日誌建議的原因,因爲它將這兩個問題都拋在了後面。 同樣適用於lambdas建議的耗時操作。希望它現在對你有幫助並且有點清楚!

1

這與Optional.orElse() vs Optional.orElseGet()差不多,第二個只在需要時才調用。

我假設記錄器內部檢查是這樣的:

if(logLevel.isDebug()){ 

     Value v = supplier.get(); 
     // log v 
} 

假設您的拉姆達使用了一些重來電來計算該值(如DB call),你肯定不希望出現這種情況計算所有時間,只在需要時。

相關問題