web-dev-qa-db-ja.com

Java静的最終変数の命名規則

次のようなルールがあります:

定数(最終変数)を表す名前は、アンダースコアを使用して単語を区切るすべて大文字である必要があります( http://geosoft.no/development/javastyle.html から取得)

intや文字列などのプリミティブ型に対しては正常に機能します。

private static final int MAX_COUNT = 10;

しかし、非プリミティブ型はどうですか?ほとんどの場合、私は以下を見ました:

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

またはインスタンス変数が大文字ではないシングルトンで。

問題は、これらのタイプの変数(ログやインスタンスなど)を宣言する正しい方法は何ですか?

85
Aleksey

それはまだconstantです。定数の命名規則の詳細については、 JLS を参照してください。しかし実際には、それはすべて好みの問題です。


インターフェース型の定数の名前は、クラス型のfinal変数は通常、1つ以上の単語、頭字語、または略語のシーケンスであり、すべて大文字で、コンポーネントはアンダースコア"_"で区切られます文字。定数名は説明的なものであり、不必要に省略してはなりません。従来、これらは音声の適切な部分である場合があります。定数の名前の例には、クラスCharacterMIN_VALUEMAX_VALUEMIN_RADIX、およびMAX_RADIXが含まれます。

セットの代替値、またはそれほど頻繁ではないが整数値のマスキングビットを表す定数のグループは、次のように、名前のプレフィックスとして共通の頭字語を使用して便利に指定されることがあります。

interface ProcessStates {
  int PS_RUNNING = 0;
  int PS_SUSPENDED = 1;
}

定数名に関係する不明瞭なことはまれです:

  • 通常、定数名には小文字が含まれないため、通常はパッケージまたはタイプの名前を隠したり、通常は少なくとも1つの小文字を含むフィールドをシャドウしません。
  • 定数名は構文的に区別されるため、メソッド名をわかりにくくすることはできません。
66
mre

これに関するダイアログは、interfaceおよびabstractクラスの命名に関する会話のアンチテーゼのようです。私はこの驚くべきことに気づき、決定は1つの命名規則を選択してstatic finalで常に使用するよりもはるかに深いと思います。

要約とインターフェース

インターフェースおよび抽象クラスに名前を付けるとき、受け入れられた規則は、クラス以外であることを示す識別情報でabstract classまたはinterfaceの前または後を付けないように進化しました。

public interface Reader {}
public abstract class FileReader implements Reader {}
public class XmlFileReader extends FileReader {}

開発者は、上記のクラスがabstractまたはinterfaceであることを知る必要がないと言われています。

静的ファイナル

私の個人的な好みと信念は、static final変数を参照するときは同様のロジックに従う必要があるということです。代わりに、名前の付け方を決定するときにその使用法を評価します。すべて大文字の引数は、CおよびC++言語からやや盲目的に採用されたもののようです。私の推定では、それはJavaの伝統を続ける正当な理由ではありません。

意図の質問

私たちは自分のコンテキストでstatic finalの機能は何かを自問する必要があります。 static final異なるコンテキストで使用する方法の3つの例を次に示します

public class ChatMessage {
    //Used like a private variable
    private static final Logger logger = LoggerFactory.getLogger(XmlFileReader.class);

    //Used like an Enum
    public class Error {
        public static final int Success = 0;
        public static final int TooLong = 1;
        public static final int IllegalCharacters = 2;
    }

    //Used to define some static, constant, publicly visible property
    public static final int MAX_SIZE = Integer.MAX_VALUE;
}

3つのシナリオすべてですべて大文字を使用できますか?もちろんですが、それぞれの目的を損なうと主張することができると思います。それでは、各ケースを個別に調べてみましょう。


目的:プライベート変数

上記のLoggerの例の場合、ロガーはプライベートとして宣言され、クラス内、または場合によっては内部クラスでのみ使用されます。 protectedで宣言されていても またはpackage可視性、その使用法は同じです:

public void send(final String message) {
    logger.info("Sending the following message: '" + message + "'.");
    //Send the message
}

ここでは、loggerstatic finalメンバー変数であることをcareしません。単にfinalインスタンス変数にすることもできます。わかりません。知る必要はありません。知る必要があるのは、クラスインスタンスが提供したロガーにメッセージを記録していることだけです。

public class ChatMessage {
    private final Logger logger = LoggerFactory.getLogger(getClass());
}

このシナリオではLOGGERという名前を付けないので、static finalである場合、なぜすべて大文字にする必要があるのでしょうか。 そのコンテキストまたは意図は、両方の状況で同じです。

注:packageレベルに制限されたpublicアクセスの形式に似ているため、package可視性の位置を逆にしました。


目的:列挙

さて、あなたはなぜstatic final整数をenumとして使用しているのでしょうか?それは まだ進化している議論 であり、私は半議論の余地があるとさえ言うだろうので、私はそれに立ち入ることによってこの議論を長い間混乱させないようにしよう。ただし、次の受け入れられた列挙パターンを実装できることが推奨されます。

public enum Error {
    Success(0),
    TooLong(1),
    IllegalCharacters(2);

    private final int value;

    private Error(final int value) {
        this.value = value;
    }

    public int value() {
        return value;
    }

    public static Error fromValue(final int value) {
        switch (value) {
        case 0:
            return Error.Success;
        case 1:
            return Error.TooLong;
        case 2:
            return Error.IllegalCharacters;
        default:
            throw new IllegalArgumentException("Unknown Error value.");
        }
    }
}

enum->intint->enumの明示的な変換を許可するという同じ目的を達成する上記のバリエーションがあります。ネットワークを介してこの情報をストリーミングする範囲では、ネイティブJavaシリアル化は単に冗長すぎます。単純なintshort、またはbyteは、帯域幅を大幅に節約できます。型の安全性、読みやすさ、保守性などを含むenum vs static final intの長所と短所について、長い比較と対照を掘り下げることができました。幸いなことに、これはこの議論の範囲外です。

一番下の行はこれです。時々static final intenumスタイル構造として使用されます

上記のステートメントがtrueであることを受け入れられるようになったら、スタイルの議論でそれをフォローできます。 enumを宣言するとき、受け入れられたスタイルは、次のことを行わないと言います。

public enum Error {
    SUCCESS(0),
    TOOLONG(1),
    ILLEGALCHARACTERS(2);
}

代わりに、次のことを行います。

public enum Error {
    Success(0),
    TooLong(1),
    IllegalCharacters(2);
}

static final整数ブロックがゆるいenumとして機能する場合、なぜ別の命名規則を使用する必要がありますか? そのコンテキストまたは意図は、両方の状況で同じです。


目的:静的、定数、パブリックプロパティ

この使用例は、おそらく最も曇っていて議論の余地があるものです。静的定数sizeの使用例は、これが最も頻繁に発生する場所です。 Java sizeof()の必要性を取り除きます 。ただし、データ構造が占有するバイト数を知ることが重要な場合があります。

たとえば、データ構造のリストをバイナリファイルに書き込んだり読み込んだりすると、そのバイナリファイルの形式では、データチャンクの合計サイズを実際のデータの前に挿入する必要があります。これは一般的であるため、読者は、シナリオでデータが停止したときに、後続の関連性のないデータがさらにあることを認識します。次の構成ファイル形式を検討してください。

File Format: MyFormat (MYFM) for example purposes only
[int filetype: MYFM]
[int version: 0] //0 - Version of MyFormat file format
[int dataSize: 325] //The data section occupies the next 325 bytes
[int checksumSize: 400] //The checksum section occupies 400 bytes after the data section (16 bytes each)
[byte[] data]
[byte[] checksum]

このファイルには、バイトストリームにシリアル化され、このファイルに書き込まれたMyObjectオブジェクトのリストが含まれています。このファイルには325バイトのMyObjectオブジェクトがありますが、各MyObjectのサイズを知らないと、どのバイトが各MyObjectに属するかを知る方法がありません。したがって、MyObjectMyObjectのサイズを定義します。

public class MyObject {
    private final long id; //It has a 64bit identifier (+8 bytes)
    private final int value; //It has a 32bit integer value (+4 bytes)
    private final boolean special; //Is it special? (+1 byte)

    public static final int SIZE = 13; //8 + 4 + 1 = 13 bytes
}

MyObjectデータ構造は、上記で定義されたファイルに書き込まれると13バイトを占有します。これを知っていると、バイナリファイルを読み取るときに、ファイル内で続くMyObjectオブジェクトの数を動的に把握できます。

int dataSize = buffer.getInt();
int totalObjects = dataSize / MyObject.SIZE;

これは、すべての大文字static final定数の典型的な使用例と引数のようです。このコンテキストでは、すべて大文字が理にかなっていることに同意します。その理由は次のとおりです。

Javaには、C言語のようなstructクラスはありませんが、structは、すべてのパブリックメンバーを持ち、コンストラクターがないクラスです。単にデータstructureです。したがって、classstructのように宣言できます。

public class MyFile {
    public static final int MYFM = 0x4D59464D; //'MYFM' another use of all uppercase!

    //The struct
    public static class MyFileHeader {
        public int fileType = MYFM;
        public int version = 0;
        public int dataSize = 0;
        public int checksumSize = 0;
    }
}

個人的にはこの方法で解析しないと述べることで、この例を序文にしましょう。代わりに、コンストラクター引数としてByteBufferまたは4つの変数すべてを受け入れることにより、内部的に解析を処理する不変クラスを提案します。つまり、このstructsメンバーにアクセス(この場合は設定)すると、次のようになります。

MyFileHeader header = new MyFileHeader();
header.fileType     = buffer.getInt();
header.version      = buffer.getInt();
header.dataSize     = buffer.getInt();
header.checksumSize = buffer.getInt();

これらはstaticfinalではありませんが、直接設定できる一般公開メンバーです。このため、static finalメンバーが公開されている場合、完全に大文字にすることは理にかなっていると思います。これは、パブリックな非静的変数と区別することが重要なの1回です。

注:この場合でも、開発者がfinal変数を設定しようとすると、IDEまたはコンパイラエラーが発生します。


概要

結論として、static final変数に選択する規則が好みになりますが、使用のコンテキストが設計上の決定に大きく影響するはずだと強く信じています。個人的には、次の2つの方法のいずれかに従うことをお勧めします。

方法1:コンテキストと意図を評価する[highly subjective; logical]

  • privateインスタンス変数と区別できないprivate変数の場合は、同じ名前を付けます。 すべて小文字
  • enum値の緩いstaticスタイルブロックのタイプとして機能することを意図している場合は、enumのように名前を付けます。 パスカルの場合:各単語の頭文字を大文字にする
  • パブリックにアクセス可能な、定数、および静的プロパティを定義することを意図している場合は、すべて大文字にすることで際立たせます

方法2:プライベートとパブリック[objective; logical]

方法2は基本的にそのコンテキストを可視性に凝縮し、解釈の余地を残しません。

  • privateまたはprotectedの場合は、すべて小文字にする必要があります
  • publicまたはpackageの場合は、すべて大文字にする必要があります

結論

これが、static final変数の命名規則を表示する方法です。私はそれが単一のキャッチオールにボックス化できる、またはすべきだとは思わない。名前の付け方を決める前に、その意図を評価すべきだと思います。

ただし、主な目的は、プロジェクト/パッケージの範囲全体で一貫性を保つことです。最後に、それはあなたが制御できるすべてです。

(私は抵抗に会うことを期待していますが、このアプローチに関してコミュニティからいくらかの支持を集めることも望みます。あなたのスタンスが何であれ、このスタイルの選択をbu責、批判、または賞賛するとき、それを市民にしてください。)

41
crush

言語は気にしません。重要なのは、作業しているプロジェクトの確立されたスタイルと慣習に従うことです。これにより、他のメンテナー(または5か月後)が混乱しないように最大限のチャンスを得ることができます。

可変オブジェクトのすべて大文字の名前は、たとえそのオブジェクトへの参照がたまたまstatic final変数に格納されていても、私を混乱させると思います。

10
Henning Makholm

それは非常に興味深い質問です。質問の2つの定数を、そのタイプに応じて分割します。 int MAX_COUNTはプリミティブ型の定数であり、Logger logは非プリミティブ型です。

プリミティブ型の定数を使用する場合、コード内で定数を1回だけ変更しますpublic static final in MAX_COUNT = 10そして、他の場所で定数の値にアクセスしますfor(int i = 0; i<MAX_COUNT; i++)。これが、この規則を使用することに慣れている理由です。

非プリミティブ型の場合は、private static final Logger log = Logger.getLogger(MyClass.class);の1か所でのみ定数を初期化しますが、log.debug("Problem")の別の場所でこの定数のメソッドを変更または呼び出すことが期待されています。私たちは大文字の後にドット演算子を置くのは好きではありません。結局、ドット演算子の後に関数名を付ける必要があります。ドット演算子は必ずキャメルケース名になります。 LOG.debug("Problem")が見苦しいのはそのためです。

Stringタイプの場合も同様です。通常、コードでString定数のメソッドを変更したり呼び出したりすることはありません。そのため、String型オブジェクトに大文字の命名規則を使用します。

7
Kashif Nazar

オブジェクトへの定数参照は定数ではなく、オブジェクトへの定数参照です。

private static finalは、何かが定数であるかどうかを定義するものではありません。定数を定義するのはJava方法にすぎませんが、すべてのprivate static final宣言が定数を定義するためにそこに置かれたことを意味するものではありません。

private static final Loggerと書くとき、定数を定義しようとはせず、private(他のクラスからはアクセスできない)、static(それはクラスレベルの変数、インスタンスは不要)およびfinal(1回のみ割り当てることができます)。 Javaが定数を宣言することを期待する方法と偶然一致した場合、それは不運ですが、定数になりません。コンパイラ、ソナー、またはJavaの第一人者が何と言っているかは気にしません。 MILLISECONDS_IN_A_SECOND = 1000のような定数値は別のものであり、オブジェクトへの定数参照は別のものです。

金は輝くことが知られていますが、輝くものすべてが金であるとは限りません。

5
Eduardo

「正しい」方法はありません-慣習のみがあります。あなたは最も一般的な慣習と、私が自分のコードで従う慣習を述べました:all static finalsはすべて大文字にする必要があります。他のチームは他の規約に従うと思います。

私の意見では、変数が「定数」であることが実装の詳細である場合が多く、必ずしも異なる命名規則を正当化するとは限りません。それは読みやすさを助けるかもしれませんが、場合によってはそれを傷つけるかもしれません。

2
Cellux

これらの変数は定数です。つまり、名前がすべて大文字であるかどうかにかかわらず、private static finalです。 all-capsの規則により、これらの変数が定数であることが明確になりますが、必須ではありません。私は見た

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

以前は小文字でした。ロガーを使用してメッセージをログに記録するだけであることがわかっているので問題ありませんが、これは慣習に違反します。あなたはそれをlogと命名することはサブコンベンションであると主張することができます。しかし、一般的に、大文字の定数の命名は正しい方法ではありませんが、最良の方法です。

1
andronikus

Sunが決めた慣習に夢中になってはいけません。あなたとあなたのチームにとって正しいと思うことをしてください。

たとえば、これはEclipseのやり方であり、慣例を破ります。 implements Serializableを追加してみると、Eclipseはこの行を生成するように求めます。

更新:除外された特殊なケースがそれを知らなかった。しかし、私はあなたとあなたのチームが適切と思われることを行うことを差し控えています。

0
Farmor