2011-07-11 43 views

回答

160
  • private - 使其他類可以劫持您記錄
  • static - 所以只有一個每個類的記錄器實例,也避免試圖序列記錄器
  • final - 無需改變日誌記錄器

此外,我更喜歡名稱log儘可能簡單,但描述性。

編輯:但是還有一個有趣的例外規則:

protected final Logger log = LoggerFactory.getLogger(getClass()); 

,而不是:

private static final Logger log = LoggerFactory.getLogger(Foo.class); 

前者的方法可以讓你使用相同的記錄器名稱(實際名稱類)遍歷繼承層次結構中的所有類。因此,如果Bar延伸Foo,則兩者都將登錄到Bar記錄器。有些人覺得更直觀。

+0

+1,答案在修飾符中。 – mre

+24

if static and final then LOG(大寫) – zacheusz

+29

* @ zacheusz *,我知道這就是要點。一些人虔誠地遵循Java命名約定(沒有什麼不妥),但我更願意寫和更愉快的閱讀'log'名稱,而不是用'LOG'分散代碼。只是開發的問題。團隊協議。 –

2

什麼時候你想改變字段的值?

如果你永遠不會改變這個值,那麼使得這個字段最終成爲明顯的,你永遠不會改變它的值。

+1

在很多情況下,顯然不添加final這個詞,它就會變成一種垃圾。 – Dima

+0

@Dima:那麼我仍然感激編譯器仍然會拋出一個錯誤,如果我*不小心嘗試在這些情況下嘗試更改值... –

2

因爲這通常是可以在您的對象的所有實例中共享的那種功能。對於同一類的兩個實例有不同的記錄器沒有太大意義(90%的時間)。

但是,你也可以看到聲明爲單身人士甚至乾脆提供靜態函數來記錄你的東西,有時記錄器類。

1

通常你初始化記錄器使用類名進行登錄 - 這意味着,如果他們不是一成不變的,你最終會具有它的一個實例(高內存佔用)類的每個實例,但所有這些記錄器將共享相同的配置並且行爲完全相同。這就是static位背後的原因。此外,因爲每個Logger被初始化與類名,以防止與子類衝突,聲明它private所以它不能被繼承。 的final來自於你不應該在執行過程中改變Logger點 - 所以一旦初始化你永遠不會「重新配置」它 - 在這種情況下,它是有道理的,使其最終確保無人可換它(通過錯誤或其他方式)。 當然,如果您打算以不同的方式使用Logger,您可能需要而不是以使用static final - 但我敢說大概猜測80%的應用程序會使用日誌記錄,如上所述。

4

static意味着你只能創建每類中的一個記錄器,每實例類的沒有一個記錄器。一般來說,這就是你想要的 - 因爲伐木者往往只根據班級而變化。

final表示您不打算更改logger變量的值。這是真的,因爲你幾乎總是把所有的日誌消息(從一個類)扔到同一個記錄器。即使在極少數情況下,類可能想要將某些消息發送到不同的記錄器,但創建另一個記錄器變量(例如widgetDetailLogger)會更清晰,而不是通過動態地變更靜態變量的值。

0

在大多數情況下,您將要更改該值,final修飾符會將其標記。對於每個類實例,您不需要單獨的實例 - 因此static首先這是爲了性能 - 它可以很好地優化(最終)並保存內存(靜態)。

3

要回答這個問題,你應該問自己什麼是「靜態」和「最終」。

對於Logger,(我假設你談論Log4J Logger類),你需要每個類的類別。這應該導致只分配一次的事實,並且每個類不需要多個實例。大概沒有理由將一個類的Logger對象暴露給另一個類,爲什麼不把它設爲私有並遵循一些面向對象原則。

另外你應該注意,編譯器能夠從中受益。所以你的代碼執行更好一點:)

7

檢查此博文:Get Rid of Java Static Loggers。這是你如何使用SLF4J與jcabi-log

import com.jcabi.log.Logger; 
class Foo { 
    void save(File f) { 
    Logger.info(this, "file %s saved successfully", f); 
    } 
} 

而且從來沒有使用靜態噪聲了。

+0

一個有趣的選擇,絕對清潔。我想知道這與個人班級記錄員相比如何。 – Ross

+5

每次寫更長的記錄器..(this,...)。羅。 –

0

除了其他答案一兩件事,我跑進是給出的理由是,如果我的記錄既不是靜態的也不是最後:

... 
public Logger logger = LoggerFactory.getLogger(DataSummary.class); 

public String toJson() { 
    GsonBuilder gsonBuilder = new GsonBuilder(); 
    return gsonBuilder.create().toJsonTree(this).toString(); 
} 
... 
在某些情況下

(我用的是GSON庫)我會得到stackoverflow異常。我的具體情況是實例化包含非靜態非最終記錄器的類。然後調用的toJSON方法,它調用GsonBuilder:

... 
DataSummary ds = new DataSummary(data);  
System.out.println(ds.toJson()); 
... 
1

此代碼是脆弱的,但Java7後,我們就可以使用Logger lgr = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); ,而不是靜態的記錄。

相關問題