次のようなルールがあります:
定数(最終変数)を表す名前は、アンダースコアを使用して単語を区切るすべて大文字である必要があります( http://geosoft.no/development/javastyle.html から取得)
intや文字列などのプリミティブ型に対しては正常に機能します。
private static final int MAX_COUNT = 10;
しかし、非プリミティブ型はどうですか?ほとんどの場合、私は以下を見ました:
private static final Logger log = Logger.getLogger(MyClass.class);
またはインスタンス変数が大文字ではないシングルトンで。
問題は、これらのタイプの変数(ログやインスタンスなど)を宣言する正しい方法は何ですか?
それはまだconstantです。定数の命名規則の詳細については、 JLS を参照してください。しかし実際には、それはすべて好みの問題です。
インターフェース型の定数の名前は、クラス型の
final
変数は通常、1つ以上の単語、頭字語、または略語のシーケンスであり、すべて大文字で、コンポーネントはアンダースコア"_"
で区切られます文字。定数名は説明的なものであり、不必要に省略してはなりません。従来、これらは音声の適切な部分である場合があります。定数の名前の例には、クラスCharacter
のMIN_VALUE
、MAX_VALUE
、MIN_RADIX
、およびMAX_RADIX
が含まれます。セットの代替値、またはそれほど頻繁ではないが整数値のマスキングビットを表す定数のグループは、次のように、名前のプレフィックスとして共通の頭字語を使用して便利に指定されることがあります。
interface ProcessStates { int PS_RUNNING = 0; int PS_SUSPENDED = 1; }
定数名に関係する不明瞭なことはまれです:
- 通常、定数名には小文字が含まれないため、通常はパッケージまたはタイプの名前を隠したり、通常は少なくとも1つの小文字を含むフィールドをシャドウしません。
- 定数名は構文的に区別されるため、メソッド名をわかりにくくすることはできません。
これに関するダイアログは、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
}
ここでは、logger
がstatic 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->int
とint->enum
の明示的な変換を許可するという同じ目的を達成する上記のバリエーションがあります。ネットワークを介してこの情報をストリーミングする範囲では、ネイティブJavaシリアル化は単に冗長すぎます。単純なint
、short
、またはbyte
は、帯域幅を大幅に節約できます。型の安全性、読みやすさ、保守性などを含むenum
vs static final int
のの長所と短所について、長い比較と対照を掘り下げることができました。幸いなことに、これはこの議論の範囲外です。
一番下の行はこれです。時々
static final int
はenum
スタイル構造として使用されます。
上記のステートメントが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
に属するかを知る方法がありません。したがって、MyObject
でMyObject
のサイズを定義します。
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
は、すべてのパブリックメンバーを持ち、コンストラクターがないクラスです。単にデータstruct
ureです。したがって、class
をstruct
のように宣言できます。
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つの変数すべてを受け入れることにより、内部的に解析を処理する不変クラスを提案します。つまり、このstruct
sメンバーにアクセス(この場合は設定)すると、次のようになります。
MyFileHeader header = new MyFileHeader();
header.fileType = buffer.getInt();
header.version = buffer.getInt();
header.dataSize = buffer.getInt();
header.checksumSize = buffer.getInt();
これらはstatic
やfinal
ではありませんが、直接設定できる一般公開メンバーです。このため、static final
メンバーが公開されている場合、完全に大文字にすることは理にかなっていると思います。これは、パブリックな非静的変数と区別することが重要なの1回です。
注:この場合でも、開発者がfinal
変数を設定しようとすると、IDEまたはコンパイラエラーが発生します。
結論として、static final
変数に選択する規則が好みになりますが、使用のコンテキストが設計上の決定に大きく影響するはずだと強く信じています。個人的には、次の2つの方法のいずれかに従うことをお勧めします。
[highly subjective; logical]
private
インスタンス変数と区別できないprivate
変数の場合は、同じ名前を付けます。 すべて小文字enum
値の緩いstatic
スタイルブロックのタイプとして機能することを意図している場合は、enum
のように名前を付けます。 パスカルの場合:各単語の頭文字を大文字にする[objective; logical]
方法2は基本的にそのコンテキストを可視性に凝縮し、解釈の余地を残しません。
private
またはprotected
の場合は、すべて小文字にする必要があります。public
またはpackage
の場合は、すべて大文字にする必要があります。これが、static final
変数の命名規則を表示する方法です。私はそれが単一のキャッチオールにボックス化できる、またはすべきだとは思わない。名前の付け方を決める前に、その意図を評価すべきだと思います。
ただし、主な目的は、プロジェクト/パッケージの範囲全体で一貫性を保つことです。最後に、それはあなたが制御できるすべてです。
(私は抵抗に会うことを期待していますが、このアプローチに関してコミュニティからいくらかの支持を集めることも望みます。あなたのスタンスが何であれ、このスタイルの選択をbu責、批判、または賞賛するとき、それを市民にしてください。)
言語は気にしません。重要なのは、作業しているプロジェクトの確立されたスタイルと慣習に従うことです。これにより、他のメンテナー(または5か月後)が混乱しないように最大限のチャンスを得ることができます。
可変オブジェクトのすべて大文字の名前は、たとえそのオブジェクトへの参照がたまたまstatic final
変数に格納されていても、私を混乱させると思います。
それは非常に興味深い質問です。質問の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
型オブジェクトに大文字の命名規則を使用します。
オブジェクトへの定数参照は定数ではなく、オブジェクトへの定数参照です。
private static final
は、何かが定数であるかどうかを定義するものではありません。定数を定義するのはJava方法にすぎませんが、すべてのprivate static final
宣言が定数を定義するためにそこに置かれたことを意味するものではありません。
private static final Logger
と書くとき、定数を定義しようとはせず、private
(他のクラスからはアクセスできない)、static
(それはクラスレベルの変数、インスタンスは不要)およびfinal
(1回のみ割り当てることができます)。 Javaが定数を宣言することを期待する方法と偶然一致した場合、それは不運ですが、定数になりません。コンパイラ、ソナー、またはJavaの第一人者が何と言っているかは気にしません。 MILLISECONDS_IN_A_SECOND = 1000
のような定数値は別のものであり、オブジェクトへの定数参照は別のものです。
金は輝くことが知られていますが、輝くものすべてが金であるとは限りません。
「正しい」方法はありません-慣習のみがあります。あなたは最も一般的な慣習と、私が自分のコードで従う慣習を述べました:all static finalsはすべて大文字にする必要があります。他のチームは他の規約に従うと思います。
私の意見では、変数が「定数」であることが実装の詳細である場合が多く、必ずしも異なる命名規則を正当化するとは限りません。それは読みやすさを助けるかもしれませんが、場合によってはそれを傷つけるかもしれません。
これらの変数は定数です。つまり、名前がすべて大文字であるかどうかにかかわらず、private static final
です。 all-capsの規則により、これらの変数が定数であることが明確になりますが、必須ではありません。私は見た
private static final Logger log = Logger.getLogger(MyClass.class);
以前は小文字でした。ロガーを使用してメッセージをログに記録するだけであることがわかっているので問題ありませんが、これは慣習に違反します。あなたはそれをlog
と命名することはサブコンベンションであると主張することができます。しかし、一般的に、大文字の定数の命名は正しい方法ではありませんが、最良の方法です。
Sunが決めた慣習に夢中になってはいけません。あなたとあなたのチームにとって正しいと思うことをしてください。
たとえば、これはEclipseのやり方であり、慣例を破ります。 implements Serializable
を追加してみると、Eclipseはこの行を生成するように求めます。
更新:除外された特殊なケースがそれを知らなかった。しかし、私はあなたとあなたのチームが適切と思われることを行うことを差し控えています。