「静的な最終ロガー」は大文字で宣言する必要がありますか?


243

Javaでは、静的なfinal変数は定数であり、慣習として、それらは大文字でなければなりません。しかし、ほとんどの人がロガーを小文字で宣言し、それがPMDの違反として現れるのを見てきました。

例えば:

private static final Logger logger = Logger.getLogger(MyClass.class);

googleまたはSOで「静的な最終ロガー」を検索すると、これが表示されます。

代わりにLOGGERを使用する必要がありますか?


PMDまたはCheckstyleは、読みやすさを向上させるための時期尚早の素朴な試みですが、利益よりも害をもたらします。最も読みやすいスタイルは、状況に応じてケースバイケースで変更できます。GuavaまたはJDK srcを参照してください。これらは厳密なスタイルテンプレートに従っていませんが、専門家によって作成されたものであることは間違いありません。例:DelegatedExecutorService @ docjar.com/html/api/java/util/concurrent/Executors.java.html
DanielHáriMar

ソナールール(rules.sonarsource.com/java/tag/convention/RSPEC-1312)にも次のように記載されていますprivate static final Logger LOGGER = LoggerFactory.getLogger(Foo.class);
ケンストンチェ

回答:


306

ロガー参照は定数ではなく、最終的な参照であり、大文字であってはなりません。定数VALUEは大文字でなければなりません。

private static final Logger logger = Logger.getLogger(MyClass.class);

private static final double MY_CONSTANT = 0.0;

42
静的な最終参照は、不変であれば定数です。このロジックでは、静的な最終文字列は参照であるため、定数文字列はありません。
Jeffrey Blattman、2013年

30
しかしjava.lang.String 不変であり、特別な種類のクラスです(String.intern()、Sringプールに関するドキュメントなどを参照してください)
Aleksander Adamowski 2013

3
不変とは、作成後にオブジェクトの状態を変更できないことを意味します。以下の私の投稿を参照してください。ロガーは必ずしも変更可能である必要はありません。
Jeffrey Blattman、2013

4
まだ誰かがこの問題に関心がある場合は、github.com / checkstyle / checkstyle / issues / 23でアイデアを共有して、大文字と小文字の区別を区別してください。
Roman Ivanov

2
@Jeach私は不変性が状態の変化に関係しているとは考えていません。また、ユーザーとは?プログラムを実行している外部ユーザー?ユーザーがボタンを押すことによって変更されている状態と、ランダムな間隔で起動するタイマーによって変更されている状態を区別しますか?(私はそうは思いません)。
Jeffrey Blattman、2014年

236

クランチドッグの答えにさらに価値を追加するために、Javaコーディングスタイルガイドでは、3.3項でこれを述べています

定数として使用されるフィールドの名前は、すべて大文字で、アンダースコアで単語を区切る必要があります。以下は定数と見なされます。

  1. すべてのstatic finalプリミティブタイプ(すべてのインターフェイスフィールドは本質的にであることを忘れないでくださいstatic final)。
  2. static final" ."(ドット)が後に続かないすべてのオブジェクト参照タイプ。
  3. static final" ["(開き角括弧)が後に続かないすべての配列。

例:

MIN_VALUE, MAX_BUFFER_SIZE, OPTIONS_FILE_NAME

この規則に従って、loggerstatic finalポイント2で述べたオブジェクト参照ですが、使用するたびに" " 続くため.、定数と見なすことができず、小文字にする必要があります。


11
これについては、これまでに見た中で最高の定義です。リンクされたドキュメントは、更新ですここに移動しているようだcs.bilgi.edu.tr/pages/standards_project/...
ロバート・

15
ポイント2がわかりません。ドットが後に続かないオブジェクトタイプの例は何ですか。すべてのオブジェクトタイプは継承さObject.equals、それらのメソッドなどを呼び出すことができます。
dogbane 2013年

6
あなたが正しいです。また、Boolean.TRUE、Boolean.FALSE、TimeUnit.MINUTES、String.CASE_INSENSITIVE_ORDER、Collections.EMPTY_LISTなどのJava定数を見ると、それらも後に続く場合があり.ます。
cbliard 2013年

5
@RomanIvanov私は再びここにそれを見つけた:scribd.com/doc/15884743/Java-Coding-Style-by-Achut-Reddy Achutレディによって書かれ、最終更新2000年5月30日
cbliard

1
2の目的は、比較対象となるクラスのみが定数と見なされることを指定することであると思います。クラスは「使用」されることを意図していません。SOME_CLASS.doStuff()を見ると、いつもうんざりしています。それは曖昧なコーディングです。これの唯一の問題は、比較のみを目的とする定数オブジェクトの一般的なケース(Stringが一般的な例です)ですが、nullチェックを回避するために、yodaスタイルのコーディングが使用され、equals()が定数で呼び出されます。私はこの2に1つの警告になるだろうと思う
ロビン・

44

効果的なJavaから、第2版、

前のルールの唯一の例外は、「定数フィールド」に関するもので、その名前は、下線文字で区切られた1つ以上の大文字の単語(たとえば、VALUESまたはNEGATIVE_INFINITY)で構成される必要があります。定数フィールドは、値が不変である静的な最終フィールドです。静的最終フィールドがプリミティブ型または不変参照型(アイテム15)を持っている場合、それは定数フィールドです。たとえば、列挙型定数は定数フィールドです。静的なfinalフィールドに変更可能な参照型がある場合でも、参照されるオブジェクトが不変であれば、それは定数フィールドである可能性があります。

要約すると、定数==静的な最終、および参照(単純型に対して)の場合、不変性。

slf4jロガーを見ると、 http://www.slf4j.org/api/org/slf4j/Logger.html

それは不変です。一方、JULロガーは変更可能です。log4jロガーも変更可能です。つまり、正しいことは、log4jまたはJULを使用している場合は「ロガー」であり、slf4jを使用している場合はLOGGERです。

上記のslf4j javadocsページには、「LOGGER」ではなく「logger」を使用する例があることに注意してください。

もちろん、これらは規則のみであり規則ではありません。たまたまslf4jを使用していて、他のフレームワークに慣れているために「ロガー」を使用したい場合、またはタイプしやすく、読みやすくする場合は、先に進んでください。


2
この推論に基づくと、checkstyleの単純化した定義は不適切です。
ロバート

3
チェックスタイルのルールがわかりません。静的ファイナルはすべて大文字にする必要があると主張しているだけなら、そうです。それは誤りです。
Jeffrey Blattman、2012年

5
Logger インターフェース はどれほど正確に不変ですか?final classStringまたはのようなInteger)のみが不変性を保証できます。SLF4Jの変更可能な実装が見つからない場合でも、Logger自分で作成するのを止めることはできません。
Costi Ciudatu 2016

なぜなら、インターフェースのメソッドは本質的に変異を許さないからです。インターフェースに変更可能な副作用を実装することもできますが、それは正しいことです。
Jeffrey Blattman

小切手スタイルのルールは、読みやすさに関係するほど成熟していない。スタイルをテンプレート化することで可読性を実現することはできません。可読性はコンテキストに応じてケースバイケースで異なる場合があります。JDKコードを参照してください。スタイルテンプレートに準拠しておらず、専門家が作成したもので、何かを示しています。
DanielHári17年

37

私はグーグルがそれを引き受けるのが好きです(グーグルJavaスタイル

すべての定数は静的最終フィールドですが、すべての静的最終フィールドが定数であるとは限りません。定数のケースを選択する前に、フィールドが本当に定数のように感じるかどうかを検討してください。たとえば、そのインスタンスの監視可能な状態のいずれかが変化する可能性がある場合、それはほぼ確実に定数ではありません。オブジェクトを変更しないことを意図するだけでは、通常は十分ではありません。

例:

// Constants
static final int NUMBER = 5;
static final ImmutableList<String> NAMES = ImmutableList.of("Ed", "Ann");
static final Joiner COMMA_JOINER = Joiner.on(',');  // because Joiner is immutable
static final SomeMutableType[] EMPTY_ARRAY = {};
enum SomeEnum { ENUM_CONSTANT }

// Not constants
static String nonFinal = "non-final";
final String nonStatic = "non-static";
static final Set<String> mutableCollection = new HashSet<String>();
static final ImmutableSet<SomeMutableType> mutableElements = ImmutableSet.of(mutable);
static final Logger logger = Logger.getLogger(MyClass.getName());
static final String[] nonEmptyArray = {"these", "can", "change"};

6
最初の文はこれを簡潔に要約していると思います:「すべての定数は静的な最終フィールドですが、すべての静的な最終フィールドが定数であるとは限りません。」機械的な考え方を使用するのは簡単で、すべての静的な最終フィールドを大文字にするだけです(これまで私はこれを行っていました)が、これは言語の繊細さを逃すためです。
ayahuasca

その引用によると、それはフィールドが定数のように「本当に感じている」かどうかということになります。私たちは精神科医ではなくエンジニアです。
Jeffrey Blattman 2017

「検討する...それが本当に定数のように感じる場合」。誰かの気持ちは、工学の分野に入るべきではありません。
ジェフリーブラットマン

次に、グアバのコードでは次のようになりますprivate static final Logger logger = Logger.getLogger(Finalizer.class.getName());
ケンストンチョイ

10

自動化ツールを使用してコーディング標準をチェックしていて、それが上記の標準に違反している場合は、それまたは標準を修正する必要があります。外部標準を使用している場合は、コードを修正します。

Sun Javaの規則は、パブリック静的定数の大文字です。明らかに、ロガーは一定ではありませんが、変更可能なものを表します(それ以外の場合、何かが起こることを期待して、ロガーのメソッドを呼び出す意味はありません)。非定数の最終フィールドに特定の標準はありません。


10
ロガーが一定ではないと言うのはなぜですか?それは確かに一定のようです。ログが生成されるのは、そのメソッドを呼び出すことの副作用ですが、監視可能な状態は変更しません。私は何か見落としてますか?
KLE

APIを確認してください。これには、メソッドの追加/取得ペアがあります。しかし、あなたの推論はとにかく欠陥があります。ロギングは観察可能です(そうでなければ、何が問題なのか)。
トム・ホーティン-タックライン2009

3
ロガーではなくStringBuilderの場合は、おそらく定数ではないでしょう。ロガーの場合でも、Logger.setLevel()などのメソッドはレシーバーを目で見て変更します。一般に大文字は、言語が定数として扱い、インライン化する定数を示します。
ピートKirkham

5
ロガーはオブジェクトへの参照であるため、定数ではありません。定数は変更できない値です。オブジェクト参照は最終的なものです(したがって、それへの参照は変更できません。たとえば、何か他のものと交換したり、nullに設定したりできます)が、オブジェクト自体は変更できます。
スポーク09/09/14

1
@JeffreyBlattman最終的なすべての参照が大文字であることに同意しませんが、好きなコーディング標準を自由に採用できます。「変更可能なオブジェクト」と「変更可能なものを表すオブジェクト」の違いがわかりにくいのは残念です。1つの例として、バックアカウント番号がありますが、それ自体は変更されませんが、可変残高へのアクセスに使用されます。詳細については、signifierとsignificandの違いを調べてください。または、不変のものが可変性をどのように表すことができるかについて、ライプニッツのモナドの概要を調べてください。
ピートカーカム2013年

7

これをググると、ロガーが静的ファイナルとして定義されていない場合があります。これに簡単なコピーアンドペーストを追加してください。これで説明が付くかもしれません。

すべてのコードでLOGGERを使用しており、これは命名規則に対応しています(そして、CheckStyleはこれに満足しています)。


さらに進んで、Eclipseの厳密な命名規則を利用しています。次のコードテンプレートを使用して新しいクラスを作成します。

    // private static final Logger LOGGER = Logger.getLogger(${enclosing_type}.class);

ロガーはコメントアウトされています。最初は必要ありません。しかし、後で必要になった場合は、コメントを外します。

次に、コードでは、このロガーが存在することを期待するコードテンプレートを使用します。try-catchテンプレートの例:

    try {
      ${cursor} or some other template
    } catch (Exception t) {
      LOGGER.error("${methodName} ${method parameters}", t);
    }

それを使用するテンプレートがいくつかあります。

厳格な規則は、私たちはより生産とコードテンプレートとコヒーレントことを可能にします


5
ログに記録して再スローしない限り、Throwableをキャッチすることは悪い習慣です。エラーを忘れないでください:OutOfMemeoryErrorなど。イベント例外は、マルチスレッドアプリケーションで自分でキャッチして処理するのは安全ではありません。
m_vitaly 2009

2
Eclipseの構文は次のとおりです。Logger.getLogger($ {enclosing_type} .class);
dogbane 2009

@fahdshariff正確な構文をありがとう。回答を更新しました。
KLE、

CheckStyleまたはPMDの「厳密な規則」が役立つ場合、GuavaおよびJDKソースに適用される共通のスタイルがないのはなぜですか?たとえば、ソースには、必要に応じて完全なインラインブロックがたくさんあります。読みやすさはコンテキストに依存するため、すべてに厳密なスタイル規則を使用すると、コンテキストベースの決定が破棄され、読みやすさが低下します。
DanielHári2017年

6

個人的には大文字で見ると本当に大きいと思います。また、クラスの振る舞いに直接関係しないクラスなので、のlogger代わりに使うことに大きな問題はないと思いますLOGGER。ただし、厳密に知識を深める場合は、を使用しますLOGGER


4

PMDはコメントを尊重することを忘れないでください

// NOPMD

初期化。これにより、PMDはその行をチェックからスキップします。これにより、必要なスタイルを選択できます。


6
またはPMDを使用しないでください。それらは常に間違っており、コードは完璧です
IAdapter

1
チェックを常に毎回除外する必要がある場合、チェックは意味がありません。
keiki 2014

これ以上同意できませんでした-ただし...除外コメントを知っておくと便利です
Fortyrunner 2014

3

通常、定数は大文字です。

ただし、ロガーは静的である必要はありませんが、slf4jファサードを使用している場合は、包含クラスのすべての「新規」を探します。これにより、特にWebコンテナーでの厄介なクラスローダーの問題がいくつか回避され、さらに、ロガーフレームワークが呼び出しコンテキストに応じて特別な処理を実行できるようになります。


2

私は「ロガー」、つまり小文字を好みます。その理由は、それが定数または定数ではない(可変または不変)ことではありません。その推論を使用する場合、ロギングフレームワークを変更する場合(またはフレームワークがロガーの可変性を変更する場合)は、変数の名前を変更する必要があります。

私にとっては、他の理由がより重要です。

  1. ロガーはクラスのシャドウオブジェクトであり、メインロジックを実装していないため、あまり目立たないはずです。「LOGGER」を使用する場合、それはあまりにも注目を集めるコードの目印です。

  2. ロガーはインスタンスレベルで宣言される場合があり(つまり、静的ではない)、依存関係として挿入されることもあります。ロガーの入手方法を変更する場合は、コードを変更したくありません。コードの安定性について。この(多くの場合は架空の)変更が、小文字を好むもう1つの理由です。


1

コーディング標準がある場合-ある場合は-大文字にする必要があると言います。

どちらにしても厳しい理由は見当たらない。私はそれはあなたの個人的ないいねレスポンスに完全に依存すると思います。会社のコーディング標準。

ところで:私は「ロガー」を好む;-)

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