ロガーをstatic finalと宣言するのはなぜですか?


131

Javaでは、ロガーを宣言することがベストプラクティスなのはなぜstatic finalですか。

private static final Logger S_LOGGER

回答:


209
  • private-他のクラスがロガーをハイジャックできないように
  • static -したがって、クラスごとに1つのロガーインスタンスのみがあり、ロガーをシリアル化する試みも回避されます
  • final -クラスの存続期間中にロガーを変更する必要はありません

また、名前logはできるだけわかりやすく、わかりやすい名前にすることをお勧めします。

編集:ただし、これらのルールには興味深い例外があります:

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

とは対照的に:

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

前者の方法では、継承階層全体のすべてのクラスで同じロガー名(実際のクラスの名前)を使用できます。つまり、Barextendsの場合Foo、両方がBarロガーに記録されます。一部の人はそれがより直感的であると思います。


35
静的で最終的な場合は、LOG(大文字)
zacheusz

39
@zacheusz、私が知っている、それがポイントです。いくつかはJavaの命名規則に忠実に従っています(何も問題はありません)がlog、でコードを分散させるよりも、名前を記述して読みやすくする方が簡単LOGです。開発者の問題だけです。チーム合意。
Tomasz Nurkiewicz

27
ロガーを静的および最終として宣言することは常に推奨されないことに注意してください。slf4j.org / faq.htmldeclared_staticおよび wiki.apache.org/commons/Logging/FrequentlyAskedQuestionsセクションを参照してください。
Matthew Farwell、2011年

6
@zacheusz大文字のフィールド名が定数に使用されます。ロガーは一定ではありません。http://stackoverflow.com/questions/1417190/should-a-static-final-logger-be-declared-in-upper-case
michal.kreuzman

2
@zacheuszすべてのstatic final属性が大文字である必要がありません。stackoverflow.com/questions/1417190/...
bsmk

15

このブログ投稿をチェックしてください:Java Static Loggerを取り除きます。これは、jcabi-logslf4jを使用する方法です。

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

そして、その静的ノイズを使用しないでください。


興味深い代替手段であり、間違いなくよりクリーンです。これは個々のクラスロガーと比較してどのようにスケールするのでしょうか。
ロス

12
より長いLogger ..(これ、...)を毎回書き込みます。いや。
ミハイルボヤルスキー2015

関連するブログ投稿の最初のコメントは、静的メソッドの悪い面を示しています:)したがって、プライベートな最終的なLoggerを使用することは、私が推測するベストプラクティスです。
バハディールTasdemir

5

staticつまり、クラスのインスタンスごとに1つのロガーではなく、クラスごとに1つのロガーを作成するだけです。一般的に、これはあなたが望むことです-ロガーはクラスだけに基づいて変化する傾向があるためです。

finallogger変数の値を変更しないことを意味します。ほとんどの場合、(1つのクラスからの)すべてのログメッセージを同じロガーにスローするため、これは真実です。クラスが別のロガーにいくつかのメッセージを送信することがまれにある場合でも、その場でwidgetDetailLogger静的変数の値を変更するのではなく、別のロガー変数(など)を作成する方がはるかに明確です。


4

フィールドの値をいつ変更しますか?

値を変更する予定がない場合は、フィールドをfinalにすると、値を変更しないことが明らかになります。


1
多くの場合、finalという単語を追加しなくても明らかですが、この場合は一種のジャンクになります。
ディマ

2
@Dima:まあ、私はまだ私がいる場合、コンパイラは、まだエラーがスローされますことを感謝しています誤ってこれらの例で値を変更しようと...
ジョンスキート

3

通常、クラス名を使用してログを記録するようにロガーを初期化します。つまり、静的でない場合、クラスの各インスタンスにインスタンス(高メモリフットプリント)が存在することになりますが、これらのロガーはすべて同じ構成を共有し、まったく同じように動作します。それがstaticビットの背後にある理由です。また、それぞれLoggerがクラス名で初期化されるため、サブクラスとの競合を防ぐために、private継承できないように宣言します。これfinalは、通常はLogger実行中にを変更しないという点から来ます。つまり、一度初期化すると、「再構成」することはありません。その場合、最終的にそれを変更して、誰も変更できないようにします(間違いまたはそれ以外の場合)。もちろん、もしあなたがLogger別の方法で使用する必要はないかもしれませんstatic finalが、上で説明したように、アプリの80%がロギングを使用すると思います。


3

その質問に答えるには、「静的」と「最終」の目的を自問する必要があります。

ロガーの場合、(私はあなたがLog4Jロガークラスについて話していると想定しています)、クラスごとにカテゴリが必要です。これにより、1回だけ割り当てることができ、クラスごとに複数のインスタンスを指定する必要はありません。そして、おそらくあるクラスのLoggerオブジェクトを別のクラスに公開する理由はないので、なぜそれを非公開にせず、いくつかのOO原則に従っていないのでしょう。

また、コンパイラはその利点を活用できることにも注意してください。したがって、コードのパフォーマンスは少し向上します:)


2

それは通常、オブジェクトのすべてのインスタンス間で共有できる機能の一種だからです。同じクラスの2つのインスタンスに異なるロガーを使用することは、あまり意味がありません(時間の90%)。

ただし、シングルトンとして宣言されたロガークラスが表示されたり、静的な関数を提供してログに記録したりする場合もあります。


2

このコードは脆弱ですが、Java7以降Logger lgr = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); 、静的ロガーの代わりに使用できます。


This is code is vulnerable少し答えてください。
Dmitry Zagorulkin

1

ほとんどの場合、参照を変更することはなく、final修飾子はそれをマークします。クラスインスタンスごとに個別のインスタンスは必要ありませんstatic。そしてまず第一に、これはパフォーマンスのためです -うまく最適化でき(最終)、メモリを節約します(静的)。


1

理想的には、ロガーはJava 7までは次のようにする必要があります。ソナーを与えず、準拠コードを与えるためです。プライベート:親クラスの外部からはアクセスできません。別のクラスが何かをログに記録する必要がある場合は、独自のロガーをインスタンス化する必要があります。static:クラス(オブジェクト)のインスタンスに依存しない。何かをログに記録する場合、もちろんコンテキスト情報をメッセージに含めることができますが、ロガーをクラスレベルで作成して、各オブジェクトと一緒にロガーが作成されないようにし、ハイメモリフットプリントを防ぐ必要があります。final:クラスごとに1回だけ作成されます。


0

他の回答で与えられた理由に加えて、私が遭遇した1つのことは、私のロガーが静的でも最終でもない場合です:

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

public String toJson() {
  GsonBuilder gsonBuilder = new GsonBuilder();   
  return gsonBuilder.create().toJsonTree(this).toString();
}
...

特定の場合(Gsonライブラリを使用していた場合)、stackoverflow例外が発生しました。私の具体的な状況は、非静的非最終ロガーを含むクラスをインスタンス化することでした。次に、GsonBuilderを呼び出したtoJsonメソッドを呼び出します。

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

0

実際、静的ロガーは静的コンテキストで動作することが想定されているため、「有害」な場合があります。動的な環境がある場合。OSGi非静的ロガーの使用が役立つ場合があります。一部のロギング実装はロガーのキャッシングを内部で行うため(AFAIKは少なくともlog4j)、パフォーマンスへの影響はごくわずかです。

静的ロガーの1つの欠点は、たとえばです。ガベージコレクション(クラスが一度だけ使用される場合、たとえば初期化中にロガーは引き続き保持されます)。

詳細については、次を確認してください。

以下も参照してください。


0

ロガーを静的にするかどうかについてインターネットから読んだ情報によると、ベストプラクティスは、ユースケースに応じて使用することです。

主な引数は2つあります。

1)静的にすると、ガベージコレクションされません(メモリ使用量とパフォーマンス)。

2)静的にしない場合、クラスインスタンスごとに作成されます(メモリ使用量)

したがって、シングルトンのロガーを作成する場合、それを静的にする必要はありません。なぜなら、インスタンスは1つだけなので、ロガーは1つだからです。

一方、モデルまたはエンティティークラスのロガーを作成する場合は、重複するロガーを作成しないように静的にする必要があります。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.