Javaでは、ロガーを宣言することがベストプラクティスなのはなぜstatic final
ですか。
private static final Logger S_LOGGER
Javaでは、ロガーを宣言することがベストプラクティスなのはなぜstatic final
ですか。
private static final Logger S_LOGGER
回答:
private
-他のクラスがロガーをハイジャックできないようにstatic
-したがって、クラスごとに1つのロガーインスタンスのみがあり、ロガーをシリアル化する試みも回避されますfinal
-クラスの存続期間中にロガーを変更する必要はありませんまた、名前log
はできるだけわかりやすく、わかりやすい名前にすることをお勧めします。
編集:ただし、これらのルールには興味深い例外があります:
protected final Logger log = LoggerFactory.getLogger(getClass());
とは対照的に:
private static final Logger log = LoggerFactory.getLogger(Foo.class);
前者の方法では、継承階層全体のすべてのクラスで同じロガー名(実際のクラスの名前)を使用できます。つまり、Bar
extendsの場合Foo
、両方がBar
ロガーに記録されます。一部の人はそれがより直感的であると思います。
log
、でコードを分散させるよりも、名前を記述して読みやすくする方が簡単LOG
です。開発者の問題だけです。チーム合意。
このブログ投稿をチェックしてください:Java Static Loggerを取り除きます。これは、jcabi-logでslf4jを使用する方法です。
import com.jcabi.log.Logger;
class Foo {
void save(File f) {
Logger.info(this, "file %s saved successfully", f);
}
}
そして、その静的ノイズを使用しないでください。
static
つまり、クラスのインスタンスごとに1つのロガーではなく、クラスごとに1つのロガーを作成するだけです。一般的に、これはあなたが望むことです-ロガーはクラスだけに基づいて変化する傾向があるためです。
final
logger
変数の値を変更しないことを意味します。ほとんどの場合、(1つのクラスからの)すべてのログメッセージを同じロガーにスローするため、これは真実です。クラスが別のロガーにいくつかのメッセージを送信することがまれにある場合でも、その場でwidgetDetailLogger
静的変数の値を変更するのではなく、別のロガー変数(など)を作成する方がはるかに明確です。
通常、クラス名を使用してログを記録するようにロガーを初期化します。つまり、静的でない場合、クラスの各インスタンスにインスタンス(高メモリフットプリント)が存在することになりますが、これらのロガーはすべて同じ構成を共有し、まったく同じように動作します。それがstatic
ビットの背後にある理由です。また、それぞれLogger
がクラス名で初期化されるため、サブクラスとの競合を防ぐために、private
継承できないように宣言します。これfinal
は、通常はLogger
実行中にを変更しないという点から来ます。つまり、一度初期化すると、「再構成」することはありません。その場合、最終的にそれを変更して、誰も変更できないようにします(間違いまたはそれ以外の場合)。もちろん、もしあなたがLogger
別の方法で使用する必要はないかもしれませんstatic final
が、上で説明したように、アプリの80%がロギングを使用すると思います。
その質問に答えるには、「静的」と「最終」の目的を自問する必要があります。
ロガーの場合、(私はあなたがLog4Jロガークラスについて話していると想定しています)、クラスごとにカテゴリが必要です。これにより、1回だけ割り当てることができ、クラスごとに複数のインスタンスを指定する必要はありません。そして、おそらくあるクラスのLoggerオブジェクトを別のクラスに公開する理由はないので、なぜそれを非公開にせず、いくつかのOO原則に従っていないのでしょう。
また、コンパイラはその利点を活用できることにも注意してください。したがって、コードのパフォーマンスは少し向上します:)
それは通常、オブジェクトのすべてのインスタンス間で共有できる機能の一種だからです。同じクラスの2つのインスタンスに異なるロガーを使用することは、あまり意味がありません(時間の90%)。
ただし、シングルトンとして宣言されたロガークラスが表示されたり、静的な関数を提供してログに記録したりする場合もあります。
このコードは脆弱ですが、Java7以降Logger lgr = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
、静的ロガーの代わりに使用できます。
This is code is vulnerable
少し答えてください。
理想的には、ロガーはJava 7までは次のようにする必要があります。ソナーを与えず、準拠コードを与えるためです。プライベート:親クラスの外部からはアクセスできません。別のクラスが何かをログに記録する必要がある場合は、独自のロガーをインスタンス化する必要があります。static:クラス(オブジェクト)のインスタンスに依存しない。何かをログに記録する場合、もちろんコンテキスト情報をメッセージに含めることができますが、ロガーをクラスレベルで作成して、各オブジェクトと一緒にロガーが作成されないようにし、ハイメモリフットプリントを防ぐ必要があります。final:クラスごとに1回だけ作成されます。
他の回答で与えられた理由に加えて、私が遭遇した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());
...
実際、静的ロガーは静的コンテキストで動作することが想定されているため、「有害」な場合があります。動的な環境がある場合。OSGi非静的ロガーの使用が役立つ場合があります。一部のロギング実装はロガーのキャッシングを内部で行うため(AFAIKは少なくともlog4j)、パフォーマンスへの影響はごくわずかです。
静的ロガーの1つの欠点は、たとえばです。ガベージコレクション(クラスが一度だけ使用される場合、たとえば初期化中にロガーは引き続き保持されます)。
詳細については、次を確認してください。
以下も参照してください。
ロガーを静的にするかどうかについてインターネットから読んだ情報によると、ベストプラクティスは、ユースケースに応じて使用することです。
主な引数は2つあります。
1)静的にすると、ガベージコレクションされません(メモリ使用量とパフォーマンス)。
2)静的にしない場合、クラスインスタンスごとに作成されます(メモリ使用量)
したがって、シングルトンのロガーを作成する場合、それを静的にする必要はありません。なぜなら、インスタンスは1つだけなので、ロガーは1つだからです。
一方、モデルまたはエンティティークラスのロガーを作成する場合は、重複するロガーを作成しないように静的にする必要があります。